c++ - erreur: passer xxx comme argument 'this' de xxx défausse les qualificatifs


#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;

Il donne une erreur que:

../main.cpp:35: erreur: passer 'const StudentT' comme 'this' argument de 'int StudentT :: getId ()' supprime les qualificatifs

../main.cpp:35: erreur: passer 'const StudentT' comme argument 'this' de 'std :: string StudentT :: getName ()' supprime les qualificatifs

Quel est le problème avec ce code? Je vous remercie!



Answers


Les objets de std::set sont stockés en tant que const StudentT . Ainsi, lorsque vous essayez d'appeler getId() avec l'objet const , le compilateur détecte un problème, à savoir que vous appelez une fonction membre non-const sur l'objet const qui n'est pas autorisée car les fonctions membres non-const ne font aucune PROMISSE objet; donc le compilateur va faire une supposition sûre que getId() pourrait essayer de modifier l'objet mais en même temps, il remarque aussi que l'objet est const; donc toute tentative de modification de l'objet const devrait être une erreur. Par conséquent, le compilateur génère un message d'erreur.

La solution est simple: rendre les fonctions const comme:

int getId() const {
    return id;
}
string getName() const {
    return name;
}

C'est nécessaire parce que maintenant vous pouvez appeler getId() et getName() sur les objets const comme:

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 sidenote, vous devez implémenter l' operator< comme:

inline bool operator< (const StudentT & s1, const StudentT & s2)
{
    return  s1.getId() < s2.getId();
}

Les paramètres de note sont maintenant des références const .




Les fonctions membres qui ne modifient pas l'instance de la classe doivent être déclarées const :

int getId() const {
    return id;
}
string getName() const {
    return name;
}

Chaque fois que vous voyez "éliminatoires éliminatoires", il s'agit de const ou volatile .




En fait, le standard C ++ (c'est-à-dire C ++ 0x draft ) dit (tnx à @Xeo & @Ben Voigt pour me l'avoir fait remarquer):

23.2.4 Conteneurs associatifs
5 Pour set et multiset, le type de valeur est le même que le type de clé. Pour la carte et multimap c'est égal à la paire. Les clés dans un conteneur associatif sont immuables.
6 itérateur d'un conteneur associatif est de la catégorie itérateur bidirectionnel. Pour les conteneurs associatifs où le type de valeur est le même que le type de clé, les deux itérateurs et const_iterator sont des itérateurs constants. Il n'est pas spécifié si itérateur et const_iterator sont du même type.

L'implémentation de VC ++ 2008 Dinkumware est donc défectueuse.

Vieille réponse:

Vous avez cette erreur car dans certaines implémentations de std lib, set::iterator est identique à set::const_iterator .

Par exemple, libstdc ++ (livré avec g ++) l'a (voir ici pour tout le code source):

typedef typename _Rep_type::const_iterator            iterator;
typedef typename _Rep_type::const_iterator            const_iterator;

Et dans les documents de SGI, il est dit:

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 se plaindre que vous appelez des méthodes non const sur set::iterator s.










Tags