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?


  • Mod

    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
    }
    

  • Mod

    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 man override 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ön override nutzen, wenn man override 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 🙄


Anmelden zum Antworten