Ich habe eine Funktion mit demselben Namen, aber mit unterschiedlicher Signatur in einer Basisklasse und abgeleiteten Klassen. Wenn ich versuche, die Funktion der Basisklasse in einer anderen Klasse zu verwenden, die von der abgeleiteten erbt, wird eine Fehlermeldung angezeigt. Siehe 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 erhalte den folgenden Fehler vom 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){};
aus der Klasse entferne B
oder aus umbenenne foo1
, funktioniert alles einwandfrei.
Was ist das Problem damit?
Antworten:
Funktionen in abgeleiteten Klassen, die Funktionen in Basisklassen nicht überschreiben, aber denselben Namen haben, verbergen andere Funktionen mit demselben Namen in der Basisklasse.
Es wird allgemein als schlechte Praxis angesehen, Funktionen in abgeleiteten Klassen zu haben, die denselben Namen haben wie Funktionen in der Bassklasse, die nicht dazu gedacht sind, die Funktionen der Basisklasse zu überschreiben, da das, was Sie sehen, normalerweise kein wünschenswertes Verhalten ist. Es ist normalerweise vorzuziehen, verschiedenen Funktionen unterschiedliche Namen zu geben.
Wenn Sie die Basisfunktion aufrufen müssen, müssen Sie den Aufruf mit verwenden
A::foo(s)
. Beachten Sie, dass dadurch auch alle virtuellen Funktionsmechanismen gleichzeitig deaktiviert werdenA::foo(string)
.quelle
Dies liegt daran, dass die Namenssuche beendet wird, wenn in einer Ihrer Basen ein Name gefunden wird. In anderen Basen wird es nicht weiter schauen. Die Funktion in B schattiert die Funktion in A. Sie müssen die Funktion von A im Bereich von B neu deklarieren, damit beide Funktionen innerhalb von B und C sichtbar sind:
Bearbeiten: Die eigentliche Beschreibung des Standards lautet (ab 10.2 / 2):
An einer anderen Stelle (direkt darüber) hat es Folgendes zu sagen:
([...] von mir gestellt). Beachten Sie, dass selbst wenn Ihr Foo in B privat ist, das Foo in A immer noch nicht gefunden wird (da die Zugriffskontrolle später erfolgt).
quelle
void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in
Klasse B kann aufgrund der lokalen Methode "int B :: foo (int)" mit demselben Namen nicht angepasst werden. Vielleicht liegt es daran, dass ich eine alte Version von gcc verwende