CodeGear 2009 [BCC32 Warnung]W8022 verbirgt virtuelle Funktion
-
Guten Morgen alle zusammen ,
ich habe bereits F1 Hilfe aufgerufen:
[ENG]
"A virtual function in a base class is usually overridden by a declaration in a derived class.
In this case, a declaration with the same name but different argument types makes the virtual functions inaccessible to further derived classes."
[GER]
"Eine virtuelle Funktion in einer Basisklasse wird in der Regel durch eine Deklaration in einer abgeleiteten Klasse außer Kraft gesetzt. In diesem Fall macht eine Deklaration mit demselben Namen, aber unterschiedlichen Argumenttypen, die virtuellen Funktionen für weitere abgeleitete Klassen unzugänglich. "Youtube hat mir auch nicht wirklich weiter geholfen
LogDriver.h(130): W8022 '_fastcall TLogDriver::C2SMsg(CMsg *,bool *)' verbirgt virtuelle Funktion '_fastcall TLogDriver::C2SMsg(EMSG *)'
Reicht es wenn ich die dargestellte virtuelle Funktion deklariere im Header-File? Bzw. was muss ich beachten, ich möchte es gerne verstehen?
-
struct A { virtual void foo(int) {cout << "A.foo\n";} virtual void bar(int) {cout << "A.bar\n";} }; struct B: public A { void foo(int, double) {cout << "B.foo\n";} }; int main() { B b; A* p = &b; p->foo(1); // A.foo p->bar(1); // A.bar b.foo(1, 1.1); // B.foo b.bar(1); // A.bar b.foo(1); // Bumm! foo(int) ist nicht sichtbar in B }
Oder andersherum, auch ein gefährlich unerwarteter Fall, wenn man sich nicht auskennt:
struct A { void foo(int) {cout << "A.foo\n";} }; struct B: public A { void foo(int) const {cout << "B.foo\n";} }; int main() { B b; A* p = &b; p->foo(1); // A.foo, nicht B.foo }
-
PS: Ich sollte vielleicht nicht nur das Problem erklären, sondern auch Lösungen
Zu Fall 2: Es sollte aus der Problemdarstellung klar geworden sein, dass die Signatur identisch sein muss, damit virtual funktioniert wie man es erwartet (und zusätzlich müssen die Rückgabetypen kompatiblel (aber nicht unbedingt identisch) sein). Man kann auch prüfen lassen, ob alles wie gewünscht funktioniert, indem manoverride
benutzt:struct B: public A { void foo(int) const override {cout << "B.foo\n";} // Bumm! Compilerfehler weil foo als override definiert ist, aber die Signatur nicht zur Base-Signatur passt };
Zu 1: Man muss halt die Basisfunktion sichtbar machen. Und vorher darüber nachdenken, ob man hier wirklich Überladung haben möchte oder sich nur vertan hat! Wenn es ein Versehen war, dann wäre auch dies mit
override
besser diagnostiziert worden. Also immer schönoverride
nutzen, wenn manoverride
meint!
So zum Beispiel geht das mit dem Sichtbarmachen:struct B: public A { void foo(int, double) {cout << "B.foo\n";} using A::foo; }; // ... b.foo(1); // Kein Bumm mehr, stattdessen A.foo
-
Dankeschön SeppJ für die ausführliche rasche Antwort, und für das anschauliche Bsp. macht das Thema eindeutig klarer für mich
Dann kann ich die Warnungen endlich angehen
Hoffentlich sind dann die Zugriffsverletzungen weck