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

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


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 .


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


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;

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.