2014-01-16 10 views
14

Erwägen Sie folgenden Code ein:C++: Überschreiben korrekt virtuelle Funktion in Template-Klasse

template<typename T> 
struct MyTempl 
{ 
    virtual void doStuff(const T &value) = 0; 
}; 

struct MyImpl : MyTempl<int> 
{ 
    void doStuff(const int &value) {} 
}; 

struct MyPtrImpl : MyTempl<int*> 
{ 
    void doStuff(const int* &value) {} 
}; 

MyImpl imp1; 
MyPtrImpl imp2; 

Dies wird nicht korrekt kompilieren: der Compiler sagt mir, dass doStuff() in MyPtrImpl rein virtuell, dh. Ich konnte es nicht richtig überschreiben. Wenn ich jedoch dedef int* zu etwas wie int_ptr, und verwenden Sie das als Vorlage Argument für MyPtrImpl, alles funktioniert.

Warum kann der Compiler meine Absicht ohne den Typdef nicht abziehen?

Antwort

17

Sie haben den korrekten Parametertyp der virtuellen Funktion nicht angegeben und überschreiben ihn nicht. Dies führt zu einer abstrakten Klasse, da die virtuelle Funktion rein ist.

Wenn ein Parameter eines const Referenztypen wie

Angabe

es ist eigentlich eine Alternative

void doStuff(int const & value) {} 

zu schreiben, die die „normale“ Art und Weise in Betracht gezogen werden sollte eine konstante Referenz zu erklären. Wenn von rechts nach links gelesen wird, bedeutet dies "eine Referenz auf die Konstante int". Die Anwendung des gleichen Musters auf den Zeigertyp int* Ergebnisse in

void doStuff(int* const & value) {} 

which compiles fine. Aber das kann nicht in der Reihenfolge wie oben geschrieben werden, da das etwas anderes bedeuten würde: Lesen Sie const int* & von rechts nach links und Sie erhalten "einen Verweis auf einen Zeiger auf eine Konstante int".

Wie Sie erwähnt, eine Alternative, die von oben mit dem Auftrag arbeitet, kann geschrieben werden, wenn Sie typedef verwenden den Zeiger Typ alias int*:

typedef int *T; 
void doStuff(const T & value) {} 

which also compiles fine, da T jetzt als einzelne wörtliche gesehen Geben Sie die Mehrdeutigkeiten nicht von oben ein. Mit anderen Worten, die einzige Möglichkeit zum Lesen von const T & ist "ein Verweis auf eine Konstante T, die selbst ein Zeiger auf int ist". Es ist ein bisschen schwierig, es intuitiv zu verstehen, aber was nicht möglich ist, ist dies als "eine Referenz auf einen Zeiger auf eine Konstante int" zu verstehen, da dies in der Beschreibung nicht eine einzigeT hätte.

Ich empfehle, das Schlüsselwort override zu verwenden, wenn Sie einen C++ 11-Compiler verwenden, um solche Probleme zu erkennen (es gibt Szenarien, in denen dieses Problem nicht zu einem Kompilierungsfehler führt, sondern zu unerwartetem Verhalten; Beispiel, wenn die virtuelle Funktion war nicht rein):

void doStuff(int* const & value) override {} 
//        ^^^^^^^^ 
+4

... weshalb die * ist richtig * Lage von 'const' ist immer die richtige. +1 –

+0

@ DavidRodríguez-dribeas Doch die meisten Leute benutzen die * linke * Version. Einschließlich der meisten Code in der Standard-Spezifikation, wenn ich mich richtig erinnere ... – leemes

+0

'lesen Sie' const int * & 'von rechts nach links und Sie erhalten" einen Verweis auf einen Zeiger auf eine Konstante int ". - Das ist alles, was ich wissen musste, danke! – Ancurio