web-dev-qa-db-fra.com

erreur: passer xxx comme argument 'this' de xxx élimine 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;

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!

397
JASON

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.

454
Nawaz

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.

80
Fred Larson

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::iterators.

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

enter image description here

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

  1. changez la méthode uint32_t getCount(){...} en uint32_t getCount() const {...}. Ainsi, count.getCount() ne changera pas les membres dans count.

ou

  1. changez 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.

1
Jayhello