c++ - Fehler: Übergeben von xxx als 'this' Argument von xxx verwirft Qualifizierer


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

In der Reihe:

cout << itr->getId() << " " << itr->getName() << endl;

Es gibt einen Fehler, der:

../main.cpp:35: Fehler: Übergabe 'const StudentT' als 'this' Argument von 'int StudentT :: getId ()' verwirft Qualifier

../main.cpp:35: Fehler: Übergabe 'const StudentT' als 'this' Argument von 'std :: string StudentT :: getName ()' verwirft Qualifier

Was ist mit diesem Code falsch? Vielen Dank!


Answers



Die Objekte in der std::set werden als const StudentT gespeichert. Wenn Sie also versuchen, getId() mit dem const Objekt getId() erkennt der Compiler ein Problem, nämlich Sie rufen eine nicht konstante Member-Funktion für const object auf, die nicht erlaubt ist, weil nicht-konstante Member-Funktionen NO PROMISE nicht Objekt; getId() der Compiler eine sichere Annahme machen, dass getId() versuchen könnte, das Objekt zu modifizieren, aber gleichzeitig bemerkt es auch, dass das Objekt const ist; Daher sollte jeder Versuch, das const-Objekt zu modifizieren, ein Fehler sein. Daher erzeugt der Compiler eine Fehlermeldung.

Die Lösung ist einfach: Stellen Sie die Funktionen const als:

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

Dies ist notwendig, da Sie jetzt getId() und getName() für const-Objekte wie getId() aufrufen können:

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
}

Als Nebenbedingung sollten Sie operator< as implementieren:

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

Hinweisparameter sind jetzt const Referenzen.




Memberfunktionen, die die Klasseninstanz nicht ändern, sollten als const deklariert werden:

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

Jedes Mal, wenn Sie "discards qualifiers" sehen, spricht man von const oder volatile .




Eigentlich sagt der C ++ Standard (also C ++ 0x Entwurf ) (; tnx an @Xeo & @Ben Voigt für das darauf hinweisen):

23.2.4 Assoziative Container
5 Für set und multiset ist der Wertetyp derselbe wie der Schlüsseltyp. Für Map und Multimap ist es gleich Pairing. Schlüssel in einem assoziativen Container sind unveränderlich.
Der 6- Iterator eines assoziativen Containers gehört zur Kategorie der bidirektionalen Iteratoren. Für assoziative Container, bei denen der Wertetyp derselbe ist wie der Schlüsseltyp, sind Iterator und const_iterator konstante Iteratoren. Es ist nicht angegeben, ob Iterator und const_iterator vom gleichen Typ sind.

Daher ist die Implementierung von VC ++ 2008 Dinkumware fehlerhaft.

Alte Antwort:

Sie haben diesen Fehler, weil in bestimmten Implementierungen der std lib der set::const_iterator derselbe ist wie set::const_iterator .

Zum Beispiel libstdc ++ (im Lieferumfang von g ++ enthalten) hat es (siehe hier für den gesamten Quellcode):

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

Und in den Dokumenten von SGI heißt es:

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.)

Auf der anderen Seite kompiliert VC ++ 2008 Express Ihren Code, ohne zu beschweren, dass Sie nicht konstante Methoden auf set::iterator s aufrufen.










Tags