Warum sollte ich das Schlüsselwort "using" verwenden, um auf meine Basisklassenmethode zuzugreifen?

75

Ich habe den folgenden Code geschrieben, um mein Problem zu erklären. Wenn ich die Zeile 11 kommentiere (mit dem Schlüsselwort "using"), 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 ParentKlasse in der SonKlasse nicht zu sehen .

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;
}
Julien Vaslet
quelle
Bitte sagen Sie mir: Was ist, wenn Sie const in "const char how" entfernen?
Pavel Radzivilovsky
31
Sie müssen nicht tippen Son s = Son();. Das erstellt nur eine temporäre und ruft dann den Kopierkonstruktor auf. Son s;
Charles Salvia
1
Warum ist C ++ so gestaltet: stackoverflow.com/questions/4837399/…
Ciro Santilli 法轮功 冠状 病 六四 事件 18

Antworten:

63

Das actionin der abgeleiteten Klasse actiondeklarierte Element verbirgt das in der Basisklasse deklarierte. Wenn Sie actionein SonObjekt verwenden, sucht der Compiler in den in deklarierten Methoden Son, findet eine aufgerufene actionund verwendet diese. Die Suche in den Methoden der Basisklasse wird nicht fortgesetzt, da bereits ein passender Name gefunden wurde.

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

Weitere Erläuterungen zu diesem Thema finden Sie auch in den C ++ - FAQ .

etw
quelle
9
@sth Gut zu wissen, dass. Aber ist das, darf ich sagen, eine Funktion von C ++ oder eine Art Fehler? verdirbt das nicht die ganze Idee der Vererbung? nur fragen ..
Sumudu
Wird der Namensabgleich mit dem verstümmelten Namen durchgeführt, spielt das Überladen von Methoden hier eine Rolle, oder wird die erste aufgerufene Funktion mit dem Namen "action" aufgerufen und das wars?
Tmaric
4
@ Anubis: Die Regel vereinfacht die Namenssuche. Ohne sie müsste der Compiler den gesamten Vererbungsbaum durchlaufen, wenn er den Namen einer Mitgliedsfunktion auflösen muss (in einigen Basisklassen kann es zu Überladungen der Funktion kommen). Mit der Regel kann der Compiler aufhören, den Rest des Vererbungsbaums zu betrachten, sobald er eine Klasse gefunden hat, die einen passenden Namen enthält. Der Programmierer befindet sich in der gleichen Situation. Wenn er sich die abgeleitete Klasse ansieht, kann er sicher sein, dass die dort definierte Funktion aufgerufen wird, ohne wissen zu müssen, ob eine Basisklasse möglicherweise eine andere Funktion mit demselben Namen enthält.
etw
18

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

Siehe C ++ - FAQ

Amnon
quelle
6

Ein Hinweis zur Vorsicht: Die Notwendigkeit, in dieser Situation ein "using" zu verwenden, ist eine rote Fahne, die Ihren Code für andere Entwickler möglicherweise verwirrt (schließlich hat er den Compiler verwirrt!). Es ist wahrscheinlich, dass Sie eine der beiden Methoden umbenennen sollten, um anderen Programmierern die Unterscheidung 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;
Dale Wilson
quelle
6

Wenn in einer abgeleiteten Klasse eine überladene Funktion neu definiert wird, wird die gesamte überladene Funktion in der Basisklasse ausgeblendet. Eine Möglichkeit, beide Funktionen einzuschließen, besteht darin, eine Funktionsüberladung in Klassen zu vermeiden. oder Sie können das verwendete usingSchlüsselwort verwenden.

Bhupesh Pant
quelle