2009-12-13 5 views
53

Ich habe den folgenden Code geschrieben, um mein Problem zu erklären. Wenn ich die Zeile 11 (mit dem Schlüsselwort "using") kommentiere, kompiliert der Compiler die Datei nicht und zeigt diesen Fehler an: invalid conversion from 'char' to 'const char*'. Es scheint die Methode void action(char) der Parent Klasse in der Son Klasse nicht zu sehen.Warum sollte ich das Schlüsselwort "using" verwenden, um auf meine Basisklassenmethode zuzugreifen?

Warum verhält sich der Compiler so? Oder habe ich etwas falsch gemacht?

class Parent 
{ 
    public: 
     virtual void action(const char how){ this->action(&how); } 
     virtual void action(const char * how) = 0; 
}; 

class Son : public Parent 
{ 
    public: 
     using Parent::action; // Why should i write this line? 
     void action(const char * how){ printf("Action: %c\n", *how); } 
}; 

int main(int argc, char** argv) 
{ 
    Son s = Son(); 
    s.action('a'); 
    return 0; 
} 
+0

Bitte sagen Sie mir: Was ist, wenn Sie const in "const char how" entfernen? –

+24

Sie müssen nicht "Son s = Son();" eingeben. Das erstellt nur ein temporäres und ruft dann den Kopierkonstruktor auf. Geben Sie einfach 'Son s;' –

+3

Wir bekommen diese Frage eine Menge: [http://stackoverflow.com/questions/1835988](http://stackoverflow.com/questions/1835988) [http://stackoverflow.com/ Fragen/411103] (http://stackoverflow.com/questions/411103) [http://stackoverflow.com/questions/1480085](http://stackoverflow.com/questions/1480085) [http: // stackoverflow. com/questions/1799497] (http://stackoverflow.com/questions/1799497) [http://stackoverflow.com/questions/888235](http://stackoverflow.com/questions/888235) [http: // stackoverflow.com/questions/72010](http://stackoverflow.com/questions/72010) –

Antwort

47

Die action in der abgeleiteten Klasse deklariert versteckt die action in der Basisklasse deklariert. Wenn Sie action auf einem Son Objekt verwenden, sucht der Compiler in den Methoden, die in Son deklariert sind, finden Sie eine action, und verwenden Sie das. Es wird nicht weiter in den Methoden der Basisklasse suchen, da es bereits einen passenden Namen gefunden hat.

Dann stimmt diese Methode nicht mit den Parametern des Aufrufs überein und Sie erhalten einen Fehler.

Siehe auch die C++ FAQ für weitere Erläuterungen zu diesem Thema.

+8

@sth Gut zu wissen, dass. aber ist das, darf ich sagen, ein Feature von C++ oder irgendeine Art von Bug? Verderbt das nicht die ganze Idee der Vererbung? nur fragen .. – Anubis

+0

Ist die Namensübereinstimmung mit dem Mangled-Namen gemacht, spielt Überladen der Methode eine Rolle hier, oder ist die erste Funktion namens, die den Namen "Aktion" hat und das ist es? – tmaric

+3

@Anubis: Die Regel vereinfacht die Namenssuche. Ohne diesen Code müsste der Compiler den vollständigen Vererbungsbaum durchlaufen, wenn er den Namen einer Elementfunktion auflösen muss (in einigen Basisklassen könnte es Überladungen der Funktion geben).Mit dieser Regel kann der Compiler den Rest der Vererbungsstruktur nicht mehr anzeigen, nachdem er eine Klasse mit einem passenden Namen gefunden hat. Der Programmierer befindet sich in der gleichen Situation. Mit Blick auf die abgeleitete Klasse kann er sicher sein, dass die dort definierte Funktion aufgerufen wird, ohne zu wissen, ob eine Basisklasse eine andere Funktion mit demselben Namen enthält. – sth

15

Überraschenderweise ist das Standardverhalten. Wenn eine abgeleitete Klasse eine Methode mit demselben Namen wie eine von der Basisklasse definierte Methode deklariert, blendet die Methode der abgeleiteten Klasse die Basisklasse ein.

Siehe C++ FAQ

5

Ein Hinweis zur Vorsicht: Die Notwendigkeit, eine "Verwendung" in dieser Situation zu verwenden, ist eine rote Flagge, dass Ihr Code für andere Entwickler verwirrend sein kann (schließlich verwirrte es den Compiler!). Es ist wahrscheinlich, dass Sie eine der beiden Methoden umbenennen sollten, um die Unterscheidung für andere Programmierer zu verdeutlichen.

Eine Möglichkeit:

void action(const char how) 
{ 
    takeAction(&how); 
} 
void action(const char * how) 
{ 
    takeAction(how); 
} 
virtual void takeAction(const char * how) = 0; 
3

Wenn in einer abgeleiteten Klasse jeden über geladene Funktion neu definiert wird dann all die überladene Funktion in der Basisklasse versteckt ist. Eine Möglichkeit, beide Funktionen einzuschließen, besteht darin, das Überladen von Funktionen in Klassen zu vermeiden. oder Sie können das Schlüsselwort using wie gewohnt verwenden.

Verwandte Themen