490 votes

erreur: en passant xxx en tant que 'ce' argument de xxx discards qualifiers

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

../main.rpc:35: erreur: passage de 'const StudentT' en tant que 'ce' argument de 'int StudentT::getId ()" rejets qualificatifs

../main.rpc:35: erreur: passage de 'const StudentT' en tant que 'ce' argument de 'std::string StudentT::getName ()" rejets qualificatifs

Quel est le problème avec ce code? Merci!!!!

557voto

Nawaz Points 148870

Les objets dans l' std::set sont stockés en tant que const StudentT. Ainsi, lorsque vous essayez d'appeler, getId() avec l' const objet le compilateur détecte un problème, à savoir que vous appelez un non-const fonction de membre sur const objet qui n'est pas autorisé, car les non-const fonctions membres ne font AUCUNE PROMESSE de ne pas modifier l'objet, de sorte que le compilateur va faire un coffre-fort hypothèse que l' getId() pourrait tenter de modifier l'objet, mais dans le même temps, il remarque également que l'objet est const; de sorte que toute tentative de modifier la const objet doit être une erreur. Donc compilateur génère un message d'erreur.

La solution est simple: rendre les fonctions const:

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

Cela est nécessaire parce que maintenant vous pouvez appeler getId() et getName() sur const objets 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
}

Au passage, vous devez implémenter operator< comme :

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

Remarque les paramètres sont maintenant const de référence.

92voto

Fred Larson Points 27404

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

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

Quand vous voyez des "rejets qualificatifs", il parle de const ou volatile.

6voto

En fait la norme C++ (c , C++ 0x projet) dit (tnx à @Xeo & @Ben Voigt pour souligner que pour moi):

23.2.4 conteneurs Associatifs
5 Pour définir et multiset le type de la valeur est le même que le type de clé. Pour la carte et multimap il est égal à la paire. Clés dans un cadre associatif conteneur sont immuables.
6 itérateur de un conteneur associatif est de la itérateur bidirectionnel de la catégorie. Pour conteneurs associatifs où la valeur le type est le même que le type de clé, à la fois iterator et const_iterator sont constante des itérateurs. Il n'est pas spécifié si oui ou non itérateur et const_iterator sont du même type.

Donc, VC++ 2008 Dinkumware mise en œuvre est défectueux.


Vieille réponse:

Vous avez cette erreur, car dans certaines implémentations de la std lib l' set::iterator est le même que set::const_iterator.

Par exemple libstdc++ (livré avec g++) (voir ici pour l'intégralité du code source):

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

Et dans le SGI docs , il est indiqué:

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 le code, sans se plaindre de ce que vous appelez non const méthodes sur set::iterators.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X