#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 ligne:
cout << itr->getId() << " " << itr->getName() << endl;
Cela donne une erreur qui:
../main.cpp:35: erreur: passer 'const StudentT' comme argument 'this' de 'int StudentT :: getId ()' ignore les qualificateurs
../main.cpp:35: erreur: passer 'const StudentT' comme argument 'this' de 'std :: string StudentT :: getName ()' ignore les qualificateurs
Quel est le problème avec ce code? Je vous remercie!
Les objets du std::set
sont stockés sous le nom const StudentT
. Ainsi, lorsque vous essayez d'appeler getId()
avec l'objet const
, le compilateur détecte un problème, vous appelez principalement une fonction membre non-const sur un objet const, ce qui n'est pas autorisé, car les fonctions membres non-const AUCUNE PROMESSE de ne pas modifier l'objet; le compilateur va donc supposer que safe suppose que getId()
pourrait tenter de modifier l'objet, mais en même temps, il remarquera que l'objet est const; toute tentative de modification de l'objet const doit donc être une erreur. Par conséquent, le compilateur génère un message d'erreur.
La solution est simple: faites les fonctions const comme:
int getId() const {
return id;
}
string getName() const {
return name;
}
Cela est nécessaire car vous pouvez maintenant appeler getId()
et getName()
sur des objets const sous la forme:
void f(const StudentT & s)
{
cout << s.getId(); //now okay, but error with your versions
cout << s.getName(); //now okay, but error with your versions
}
En tant que note de bas de page, vous devez implémenter operator<
comme:
inline bool operator< (const StudentT & s1, const StudentT & s2)
{
return s1.getId() < s2.getId();
}
Les paramètres de note sont maintenant const
référence.
Les fonctions membres qui ne modifient pas l'instance de classe doivent être déclarées comme const
:
int getId() const {
return id;
}
string getName() const {
return name;
}
Chaque fois que vous voyez des "qualificateurs de rejet", il est question de const
ou volatile
.
En réalité, le standard C++ (c'est-à-dire brouillon C++ 0x ) dit (tnx à @Xeo & @Ben Voigt pour m'avoir signalé cela):
23.2.4 Conteneurs associatifs
5 Pour set et multiset, le type de valeur est identique au type de clé. Pour les cartes et les cartes multiples, c'est égal à paire. Les clés d'un conteneur associatif sont immuables.
6 l'itérateur d'un conteneur associatif appartient à la catégorie des itérateurs bidirectionnels. Pour les conteneurs associatifs où le type de valeur est identique au type de clé, l'itérateur et const_iterator sont des itérateurs constants. Il n'est pas précisé si l'itérateur et const_iterator sont du même type.
Donc, l’implémentation de VC++ 2008 Dinkumware est défectueuse.
Ancienne réponse:
Vous avez cette erreur car dans certaines implémentations de la bibliothèque std, le set::iterator
est identique à set::const_iterator
.
Par exemple, libstdc ++ (livré avec g ++) l’a (voir here pour le code source complet):
typedef typename _Rep_type::const_iterator iterator;
typedef typename _Rep_type::const_iterator const_iterator;
Et dans SGI docs il est écrit:
iterator Container Iterator used to iterate through a set.
const_iterator Container Const iterator used to iterate through a set. (Iterator and const_iterator are the same type.)
D'autre part, VC++ 2008 Express compile votre code sans vous plaindre d'appeler des méthodes non const sur set::iterator
s.
Laissez-moi vous donner un exemple plus détaillé. En ce qui concerne la structure ci-dessous:
struct Count{
uint32_t c;
Count(uint32_t i=0):c(i){}
uint32_t getCount(){
return c;
}
uint32_t add(const Count& count){
uint32_t total = c + count.getCount();
return total;
}
};
Comme vous le voyez ci-dessus, l'IDE (CLion) vous donnera des astuces Non-const function 'getCount' is called on the const object
. Dans la méthode add
count
est déclaré en tant qu'objet const, mais la méthode getCount
n'est pas une méthode const, de sorte que count.getCount()
peut modifier les membres dans count
.
Erreur de compilation comme ci-dessous (message principal dans mon compilateur):
error: passing 'const xy_stl::Count' as 'this' argument discards qualifiers [-fpermissive]
Pour résoudre le problème ci-dessus, vous pouvez:
uint32_t getCount(){...}
en uint32_t getCount() const {...}
. Ainsi, count.getCount()
ne changera pas les membres dans count
.ou
uint32_t add(const Count& count){...}
en uint32_t add(Count& count){...}
. Donc, count
ne s’occupe pas de changer de membre.En ce qui concerne votre problème, les objets de std :: set sont stockés sous la forme constante StudentT, mais les méthodes getId
et getName
ne sont pas constantes. Vous indiquez donc l'erreur ci-dessus.
Vous pouvez également voir cette question Signification de 'const' en dernier dans une déclaration de fonction d'une classe? pour plus de détails.