Frage

Ich habe eine Funktion mit dem gleichen Namen, aber mit unterschiedlicher Signatur in einer Base und abgeleiteten Klassen. Wenn ich versuche, die Basisklasse Funktion in einer anderen Klasse zu verwenden, das von der abgeleiteten erbt, erhalte ich einen Fehler. Siehe den folgenden Code:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

ich die folgende Fehlermeldung aus den gcc-Compiler:

In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)

Wenn ich int foo(int i){}; von Klasse B entfernen, oder wenn ich es von foo1 umbenennen, funktioniert alles einwandfrei.

Was ist das Problem mit diesem?

War es hilfreich?

Lösung

Funktionen in abgeleiteten Klassen, die Funktionen in Basisklassen nicht außer Kraft setzen, die jedoch in demselben Namen verbergen andere Funktionen des gleichen Namens in der Basisklasse.

Es ist allgemein schlechte Praxis zu haben, haben Funktionen in abgeleiteten Klassen betrachtet, die die gleichen Namen wie Funktionen in der Bass-Klasse haben, die nicht dazu bestimmt sind, die Basisklasse Funktionen wie außer Kraft zu setzen, was Sie sehen normalerweise nicht erwünschtes Verhalten sind. Es ist in der Regel bevorzugt, verschiedene Funktionen verschiedene Namen zu geben.

Wenn Sie die Basis-Funktion aufzurufen benötigen Sie den Anruf Umfang müssen durch A::foo(s) verwenden. Beachten Sie, dass dies würde auch jeden virtuellen Funktionsmechanismus für A::foo(string) zur gleichen Zeit deaktivieren.

Andere Tipps

Es ist, weil Namenssuche stoppt, wenn es einen Namen in einem Ihrer Basen findet. Es wird nicht über in anderen Basen suchen. Die Funktion in B Schatten die Funktion in A. Sie haben die Funktion von A im Rahmen von B neu zu erklären, so dass beide Funktionen sichtbar sind von innen B und C:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
    using A::foo;
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

Edit: Die eigentliche Beschreibung der Norm gibt (ab 10.2 / 2):

  

Die folgenden Schritte definieren das Ergebnis der Namenssuche in einem Klassenbereich, C. Zunächst jede Erklärung für die   Namen in der Klasse und in jedem seiner Basisklasse Unterobjekte betrachtet. Einen Mitgliedsnamen f in einem sub-   Objekt B verbirgt ein Elementname f in einer A-Unterobjekt, wenn A eine Basisklasse Subobjekt von B. Jede Erklärungen ist   die sind so aus der Betrachtung ausgeschlossen versteckt. Jede dieser Erklärungen, die durch eine eingeführte   Verwendung Deklaration wird als von jedem Unterobjekt von C sein, die von der Art ist, die Deklarationen enthält,   tion durch die Verwendung-declaration.96 bezeichnet) Wenn die resultierende Menge von Deklarationen nicht alle von Unterobjekten sind   den gleichen Typs, oder hat das Set ein nicht-statisches Element und umfasst Mitglieder aus unterschiedlichen Unterobjekten, bestehen   eine Zweideutigkeit und das Programm schlecht ausgebildet. Ansonsten dieser Satz ist das Ergebnis der Suche.

Es hat den folgenden an einem anderen Ort zu sagen (darüber nur):

  

Für eine id-Ausdruck [ so etwas wie "foo" ], Namen-Suche beginnt in der Klasse Anwendungsbereich dieser; für eine qualifizierte-ID [ so etwas wie "A :: foo" ist A ein Nested-name-Bezeichner ], Namenssuche im Rahmen des verschachtelten-name-Bezeichner beginnt. Namenssuche erfolgt vor Zugriffskontrolle (3.4, Ziffer 11).

([...] von mir gestellt). Beachten Sie, dass bedeutet, dass selbst wenn Ihr foo in B privat ist, wird die foo in A noch nicht gefunden werden (weil Zugriffskontrolle geschieht später).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top