Erneute Deklaration in abgeleiteter Klasse



  • Hallo,

    meine C++ Kentnisse sind /etwas/ eingerostet. Trotzdem arbeite ich mich gerade in einen neuen Code ein. Dort ist mir folgendes aufgefallen:

    #include <iostream>
    using namespace std;
    
    // HPP-File
    
    class A {
    public:
      virtual void init(int i) = 0;
    };
    
    class B : public A {
    public:
      virtual void init(int i) = 0;
    };
    
    class C : public B {
    public:
      virtual void init(int i);
    };
    
    // CPP-File
    
    void C::init(int i) {
      cout<<"C::A "<<i<<endl;
    }
    

    init() wird also in A rein virtuell deklariert. Warum wird es in B erneut deklariert? Das scheit unnötig zu sein, mein Testcode funtioniert auch so.

    Die dritte Deklaration von init() in C ist allerdings notwendig, damit ich es dann in C::init() definieren kann. Stimmt das so? (eigentlich dachte ich zuerst, dass auch die Deklaration von init() in C unnötig ist, sondern einfach überschrieben wird, aber dem ist wohl nicht so).

    Vielen Dank & Grüße!



  • Horus107 schrieb:

    Warum wird es in B erneut deklariert?

    Keine Ahnung! Evtl. ist das die einzige nicht definierte Methode in B und deshalb eine Möglichkeit zu zeigen/erkennen, dass B abstrakt ist.



  • Die erneute Deklaration in B ist in der Tat unnötig. Man könnte jetzt argumentieren, dass man dadurch dem Leser klar macht, dass es in B noch eine pure virtuelle Methode gibt. Ansonsten wäre B leer und der Leser wüsste nicht, ohne A zu untersuchen, ob es pure virtuelle Methoden gibt. IMO eine Frage des Stils.

    Die (erneute) Deklaration in C ist notwendig, damit der Compiler weiß ab wann die Methode nicht mehr pur-virtuell ist! Man kann nämlich auch für die puren virtuellen Methoden eine Definition angeben und diese somit auch in den abgeleiteten Klassen aufrufen. Eine Definition reicht also nicht aus um zu zeigen, dass eine Methode pur oder nicht pur ist.



  • Horus107 schrieb:

    init() wird also in A rein virtuell deklariert. Warum wird es in B erneut deklariert? Das scheit unnötig zu sein, mein Testcode funtioniert auch so.

    Hast recht, da ist es unnötig.
    Ein Kommentar würde auch reichen, wenn man nicht aus versehen vergessen will, daß B abstrakt ist.

    class B : public A {
    public:
      //virtual void init(int i)=0; in A
    };
    

    Horus107 schrieb:

    Die dritte Deklaration von init() in C ist allerdings notwendig, damit ich es dann in C::init() definieren kann. Stimmt das so?

    Jo! Vielleicht, daß mein Kollege sie nicht aus versehen definiert.



  • Biolunar schrieb:

    Die (erneute) Deklaration in C ist notwendig, damit der Compiler weiß ab wann die Methode nicht mehr pur-virtuell ist! Man kann nämlich auch für die puren virtuellen Methoden eine Definition angeben und diese somit auch in den abgeleiteten Klassen aufrufen. Eine Definition reicht also nicht aus um zu zeigen, dass eine Methode pur oder nicht pur ist.

    Wie sähe denn sowas aus? Also eine Definiton für eine pur-virtuelle Methode (z.B. B::init) und diese dann in C verwenden. So hat es bei mir nicht geklappt:

    #include <iostream>
    using namespace std;
    
    // HPP-File
    
    class A {
    public:
      virtual void init(int i) = 0;
    };
    
    class B : public A {
    public:
      virtual void init(int i) = 0;
    };
    
    class C : public B {
    public:
      virtual void init(int i);
    };
    
    // CPP-File
    
    void B::init(int i) {
      cout<<"B::A "<<i<<endl;
    }
    
    // void C::init(int i) {
    //   cout<<"C::A "<<i<<endl;
    // }
    
    int main(int argc, char* argv[])
    {
      // B b;
      C c;
      // b.init(1);
      c.init(2);
    
    }
    


  • Du musst C::init trotzdem noch definieren, kannst aber B::init aufrufen:

    void C:init(int i)
    {
      B::init(i);
    }
    


  • Du brauchtst schon noch die Definition von init in C.

    #include <iostream>
    using namespace std;
    
    class A {
    public:
      virtual void init(int i) = 0;
    };
    
    class B : public A {
    public:
      virtual void init(int i) = 0;
    };
    
    class C : public B {
    public:
      virtual void init(int i);
    };
    
    void B::init(int i) {
      cout<<"B::A "<<i<<endl;
    }
    
    void C::init(int i) {
      B::init(i); // hier kannst du die pure virtuelle Methode aufrufen, weil du eine Definition von dieser hast
      cout<<"C::A "<<i<<endl;
    }
    
    int main(int argc, char* argv[])
    {
      C c;
      //c.A::init(4); // fehler, da keine Definition
      c.B::init(3); // geht auch
      c.init(2);
    }
    

Log in to reply