#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;
}
En línea:
cout << itr->getId() << " " << itr->getName() << endl;
Da un error que:
../main.cpp:35: error: pasar 'const StudentT' como 'este' argumento de 'int StudentT :: getId ()' descarta los calificadores
../main.cpp:35: error: pasar 'const StudentT' como 'este' argumento de 'std :: string StudentT :: getName ()' descarta los calificadores
¿Qué tiene de malo este código? ¡Gracias!
volatile
Respuestas:
Los objetos en el
std::set
se almacenan comoconst StudentT
. Entonces, cuando intentas llamargetId()
con elconst
objeto, el compilador detecta un problema, principalmente estás llamando a una función miembro no constante en el objeto constante que no está permitida porque las funciones miembro no constantes NO PROMETEN NO modificar el objeto; así que el compilador hará una suposición segura quegetId()
podría intentar modificar el objeto pero al mismo tiempo, también se da cuenta de que el objeto es constante; entonces cualquier intento de modificar el objeto const debería ser un error. Por lo tanto, el compilador genera un mensaje de error.La solución es simple: hacer las funciones constantes como:
Esto es necesario porque ahora puede llamar
getId()
ygetName()
en objetos const como:Como nota al margen, debe implementar
operator<
como:Los parámetros de nota ahora son de
const
referencia.fuente
const StudentT & s1, const StudentT & s2
?const
debido a que la función no necesita modificar el objeto, por lo que seconst
aplica en tiempo de compilación.Las funciones miembro que no modifican la instancia de clase deben declararse como
const
:Cada vez que ves "calificadores de descarte", se trata de
const
ovolatile
.fuente
const
viene el aquí, pero sospecho queset
está devolviendo una referencia constante del iterador para evitar que la instancia cambie y, por lo tanto, invalide el conjunto.foo obj;
aconst foo obj;
una vez y vea qué sucede. O pasar unaconst
referencia a afoo
.set
se cambian los elementos en a , el orden se puede alterar y el conjunto ya no es válido. En amap
, solo la clave esconst
. En aset
, todo el objeto es realmente la clave.f()
en mi respuesta.En realidad, el estándar C ++ (es decir, C ++ 0x draft ) dice (tnx a @Xeo y @Ben Voigt por señalarme eso):
Entonces, la implementación de VC ++ 2008 Dinkumware es defectuosa.
Vieja respuesta:
Obtuviste ese error porque en ciertas implementaciones de std lib
set::iterator
es igual queset::const_iterator
.Por ejemplo, libstdc ++ (incluido con g ++) lo tiene (consulte aquí el código fuente completo):
Y en los documentos de SGI dice:
Por otro lado, VC ++ 2008 Express compila su código sin quejarse de que está llamando a métodos no constantes en
set::iterator
s.fuente
Permítanme dar un ejemplo más detallado. En cuanto a la siguiente estructura:
Como ve lo anterior, el IDE (CLion) le dará consejos
Non-const function 'getCount' is called on the const object
. En el métodoadd
count
se declara como objeto const, pero el métodogetCount
no es const, por lo quecount.getCount()
puede cambiar los miembros encount
.Error de compilación como se muestra a continuación (mensaje principal en mi compilador):
Para resolver el problema anterior, puede:
uint32_t getCount(){...}
auint32_t getCount() const {...}
. Entoncescount.getCount()
no cambiará a los miembroscount
.o
uint32_t add(const Count& count){...}
auint32_t add(Count& count){...}
. Así quecount
no me importa cambiar miembros en él.En cuanto a su problema, los objetos en std :: set se almacenan como const StudentT, pero son el método
getId
ygetName
no son const, por lo que da el error anterior.También puede ver esta pregunta ¿Qué significa 'const' último en una declaración de función de una clase? para más detalles.
fuente