#include <iostream>
#include <set>
using namespace std;
class StudentT {
public:
int id;
string name;
public:
StudentT(int _id, string _name) : id(_id), name(_name) {
}
int getId() {
return id;
}
string getName() {
return name;
}
};
inline bool operator< (StudentT s1, StudentT s2) {
return s1.getId() < s2.getId();
}
int main() {
set<StudentT> st;
StudentT s1(0, "Tom");
StudentT s2(1, "Tim");
st.insert(s1);
st.insert(s2);
set<StudentT> :: iterator itr;
for (itr = st.begin(); itr != st.end(); itr++) {
cout << itr->getId() << " " << itr->getName() << endl;
}
return 0;
}
Na linha:
cout << itr->getId() << " " << itr->getName() << endl;
Dá um erro que:
../main.cpp:35: erro: passar 'const StudentT' como 'this' argumento de 'int StudentT :: getId ()' descarta qualificadores
../main.cpp:35: erro: passar 'const StudentT' como 'this' argumento de 'std :: string StudentT :: getName ()' descarta qualificadores
O que há de errado com este código? Obrigado!
volatile
Respostas:
Os objetos no
std::set
são armazenados comoconst StudentT
. Portanto, quando você tenta chamargetId()
oconst
objeto, o compilador detecta um problema, principalmente você está chamando uma função de membro não-const no objeto const, o que não é permitido porque as funções de membro que não fazem const NÃO prometem não modificar o objeto; portanto, o compilador fará uma suposição segura quegetId()
pode tentar modificar o objeto, mas, ao mesmo tempo, também nota que o objeto é const; portanto, qualquer tentativa de modificar o objeto const deve ser um erro. Portanto, o compilador gera uma mensagem de erro.A solução é simples: torne as funções constantes como:
Isso é necessário porque agora você pode chamar
getId()
egetName()
const objetos como:Como nota de rodapé, você deve implementar
operator<
como:Os parâmetros de nota agora são
const
referência.fonte
const StudentT & s1, const StudentT & s2
?const
como a função não precisa modificar o objeto, a aplicação éconst
imposta no momento da compilação.As funções de membro que não modificam a instância da classe devem ser declaradas como
const
:Sempre que você vê "descarta qualificadores", está falando sobre
const
ouvolatile
.fonte
const
está vindo, mas suspeito queset
esteja retornando uma referência const do iterador para impedir que a instância seja alterada e, assim, invalidar o conjunto.foo obj;
paraconst foo obj;
uma vez e veja o que acontece. Ou passe umaconst
referência para afoo
.set
forem alterados, a ordem poderá ser alterada e o conjunto não será mais válido. Em amap
, apenas a chave éconst
. Em aset
, todo o objeto é realmente a chave.f()
na minha resposta.Na verdade, o padrão C ++ (ou seja, rascunho C ++ 0x ) diz (tnx para @Xeo e @Ben Voigt por apontar isso para mim):
Portanto, a implementação do VC ++ 2008 Dinkumware está com defeito.
Resposta antiga:
Você recebeu esse erro porque em certas implementações da lib std
set::iterator
é o mesmo queset::const_iterator
.Por exemplo, o libstdc ++ (fornecido com o g ++) possui (veja aqui o código-fonte inteiro):
E nos documentos da SGI , afirma:
Por outro lado, o VC ++ 2008 Express compila seu código sem reclamar que você está chamando métodos não const em
set::iterator
s.fonte
Vamos dar um exemplo mais detalhado. Quanto à estrutura abaixo:
Como você vê acima, o IDE (CLion), dará dicas
Non-const function 'getCount' is called on the const object
. No métodoadd
count
é declarado como objeto const, mas o métodogetCount
não é const, portanto,count.getCount()
pode alterar os membros emcount
.Erro de compilação como abaixo (mensagem principal no meu compilador):
Para resolver o problema acima, você pode:
uint32_t getCount(){...}
parauint32_t getCount() const {...}
. Entãocount.getCount()
não vai mudar os membroscount
.ou
uint32_t add(const Count& count){...}
parauint32_t add(Count& count){...}
. Portantocount
, não se importe em mudar de membro.Quanto ao seu problema, os objetos no std :: set são armazenados como const StudentT, mas o método
getId
egetName
não são const, portanto, você fornece o erro acima.Você também pode ver esta pergunta Significado de 'const' por último em uma declaração de função de uma classe? para mais detalhes.
fonte