2015-10-21 4 views

Antwort

13

Die beiden Funktionen sind eigentlich nicht die gleichen. Nur die zweite Funktion wird als const Elementfunktion deklariert. Wenn das Objekt, von dem das Mitglied aufgerufen wird, const ist, wird die letztere Option verwendet. Wenn das Objekt nicht const ist, wird die erste Option verwendet.

Beispiel:

void any_func(const Type *t) 
{ 
    something = t->value(); //second `const` version used 
} 

void any_func2(Type *t) 
{ 
    something = t->value(); //first non-`const` version used 
} 

Wenn beide Funktionen nicht erklärt wurden const oder beide const erklärt wurden, den Compiler würde (sollte jedenfalls) beschweren.

7

Warum der Compiler nicht über

Da die const zählt für eine andere Funktion Unterschrift beschweren. Ihre Annahme die Funktionssignaturen sind identisch ist falsch.
Die als const markierte Funktion wird für jede Instanz const oder Referenznummer Type<T> aufgerufen.

und wie weiß man, welcher aufgerufen wird?

Legen Sie eine cout Anweisung in den Funktionen und testen Sie die folgenden Fälle:

template <class T> 
class Type { 
    public: 
     Type() {} 
     T& operator=(const T& rhs) {value() = rhs; return value();} 
     T& value() { 
      std::cout << "non const version" << std endl; 
      return m_value; 
     } 
     T value() const { 
      std::cout << "const version" << std endl; 
      return m_value; 
     } 
    private: 
     T m_value; 
}; 

int main() { 
    Type<int> t; 
    t.value(); 

    Type<int> rt = t; 
    rt.value(); 

    Type<int>* pt = &t; 
    pt->value(); 

    const Type<int> ct; 
    ct.value(); 

    const Type<int>& crt = t; 
    crt.value(); 

    const Type<int>* pct = &t; 
    pct->value(); 
} 

Ihre Zuweisungsoperator die nicht const Version aufrufen.


Die const Version sollte

const T& value() const { 
    std::cout << "const version" << std endl; 
    return m_value; 
} 

besser aussehen wie, weil man nicht immer auf RVO (Optimierung Rückgabewert) verlassen kann, und zusätzliche Kopien könnten (vor allem für ältere Compiler-Implementierungen) entnommen werden.


Beachten Sie auch die Zuweisungsoperator einen Verweis auf die aktuelle Instanz zurückgeben sollte:

Type& operator=(const T& rhs) {value() = rhs; return *this;} 
5

Ein paar Worte auf Funktionen Auflösung Priorität. Compiler unterscheidet zwischen const/non const Funktionen auf folgenden Weg:

Wenn eine Klasse nur const Funktion mit Vornamen und Argumentliste hat, wird es für konstante und nicht konstante Objekte gleichermaßen aufgerufen.Nach dem Aufruf dieser Funktion wird das Objekt "constness" annehmen (auch wenn es nicht const ist), was bedeutet, dass die Funktion nur andere const-Funktionen aufrufen kann.

Wenn eine Klasse nur eine nicht konstante Funktion hat, wird sie für nicht konstante Objekte aufgerufen. Der Versuch, diese Funktion für konstante Objekte aufzurufen, führt zu einem Kompilierungsfehler.

Wenn eine Klasse beide Funktionen zur Verfügung hat, wird die const-Version für konstante Objekte verwendet, die nicht-konstante Version wird für nicht-konstante Objekte verwendet.

Danke an @owacoder für meine Aufmerksamkeit auf die erste Verwechslung in der Beschreibung.

+3

Ich denke, die Logik im zweiten Absatz ist rückwärts. Nicht-const-Funktionen ** können nicht für const-Objekte aufgerufen werden. – owacoder

+0

@owacoder, natürlich können sie. Versuche es selbst. – SergeyA

+0

@owacoder, mein Schlechter. Du hast Recht, ich habe deinen Kommentar falsch gelesen und meine Antwort falsch geschrieben. Wird es bearbeiten. – SergeyA

Verwandte Themen