Wie mache ich eine Klasse virtuell



  • struct foo
    {
      virtual ~foo() = 0;
    };
    foo::~foo() { }
    
    struct bar : foo
    {
      virtual void whatever() = 0;
    };
    void bar::whatever() { std::cout << "..." << std::endl; }
    
    struct baz : bar
    {
      void whatever();
    };
    void baz::whatever() { bar::whatever(); }
    


  • Man kann die Funktion nicht definieren!!

    Doch und ob man das kann.

    ISO Standard 10.4/2 schrieb:

    An abstract class is a class that can be used only as a base class of some other class; no objects of an abstract class can be created except as subobjects of a class derived from it. A class is abstract if it has at least one pure virtual function. A virtual function is specified pure by using a purespecifier (9.2) in the function declaration in the class declaration. A pure virtual function need be defined only if explicitly called with the qualifiedid syntax (5.1).

    Folgender Code ist absolut korrekt:

    class Foo{
    public:
      virtual void bar()=0;
    };
    
    void Foo::bar(){
    
    }
    

    Bedenkte ich kann Foo::bar immer aufrufen wenn ich Foo::bar und nicht nur bar schreibe.

    Da ein Destruktor immer implizit den Destruktor der Basisklasse aufruft muss dieser definiert sein.

    Was allerdings nicht geht ist folgendes

    class Foo{
    public:
      virtual void bar()=0{};
    };
    

    Eine pure virtuelle Funktion kann nicht in der Klassendefinition definiert werden.

    Wieso er bei deinem zweitem Bespiel meckert sollte offensichtlich sein.



  • class Basis
    {
    public:
      virtual ~Basis() =0;
    };
    
    Basis::~Basis()
    { /* ... */ }
    
    class Abgeleitet : public Basis
    {
    public:
      virtual ~Abgeleitet() =0;
    };
    
    Abgeleitet::~Abgeleitet()
    { /* ... */ }
    
    int main()
    {
      // Basis a;
      Abgeleitet a;
    }
    

    main.cpp: In function int main()': main.cpp:28: error: cannot declare variable \a' to be of type `Abgeleitet'
    main.cpp:28: error: because the following virtual functions are abstract:
    main.cpp:21: error: virtual Abgeleitet::~Abgeleitet()
    main.cpp:21: error: virtual Abgeleitet::~Abgeleitet()

    Dass es nicht möglich ist eine Instanz von der Klasse Basis zu erstellen ist klar, da es sich hiebei um eine rein-virtuelle Schnittstelle handelt. Dieses Interface dient der Klasse Abgeleitet als Basisklasse. Wenn es stimmt, was du sagst, muss es möglich sein eine Instanz von der Klasse Abgeleitet zu erstellen, _ohne_ die Deklaration der Klasse Basis zu veränder. Wenn du mir eine Möglichkeit zeigst, eine Instanz von der Klasse Abgeleitet zu erzeugen muss ich eingestehen, dass du Recht hast... Jetzt bin ich gespannt!



  • Bitteschön

    class Basis
    {
    public:
      virtual ~Basis() =0;
    };
    
    Basis::~Basis()
    { /* ... */ }
    
    class Abgeleitet : public Basis
    {
    public:
      virtual ~Abgeleitet();
    };
    
    Abgeleitet::~Abgeleitet()
    { /* ... */ }
    
    int main()
    {
      // Basis a;
      Abgeleitet a;
    }
    

    Du hast abgeleitet (unabsichtlich?) ebenfalls zu ner abstrakten Klasse gemacht.



  • Keiner hat behauptet, das alle pure virtual sein sollen. Irgendwann muß sich das ändern. Das hat aber auch keiner anders behauptet, worauf Du also gespannt bist ist mir schleierhaft.

    Das hingegen:

    class Basis
    {
    public:
      virtual ~Basis() =0;
    };
    
    Basis::~Basis()
    { /* ... */ }
    
    class Abgeleitet : public Basis
    {
    public:
      virtual ~Abgeleitet(); // = 0;
    };
    
    Abgeleitet::~Abgeleitet()
    { /* ... */ }
    
    int main()
    {
      // Basis a;
      Abgeleitet a;
    }
    

    geht wunderbar, und ich habe nicht die Deklaration von Basis verändert, ganz wie gewünscht. Destruktor rein-virtuell und mit Definition schliessen sich also nicht aus. 🤡



  • Alle rein-virtuellen Methoden müssen überschrieben werden, damit von einer Klasse instanzen gemacht werden können. Ich bin fest davon ausgegangen, dass man den Destruktor einer Klasse nicht überschreiben kann, da sich die Signatur des Destruktors ändert. Du hast gewonnen und ich hab noch ein wenig dazugelernt! 🙂
    Ich habe mich zwar mit Sachen wie z.B. die Metaprogrammierung beschäftigt, aber dass man Destruktoren rein-virtuell deklarieren kann das war mir neu...



  • Ich wusst doch, dass ich irgendwo gelesen hab, dass virtuelle Funktionen nen Körper haben dürfen... Naja, jetzt werd ich mirs merken 🙂



  • rein virtuelle Funktionen dürfen so oder so einen Funktionskörper sprich eine Definition haben, das ist keine Frage. Sicher meinst du die rein-virtuellen Funktionen.

    Das ist schon ein wenig verwirrend, die Ähnlichkeit der beiden Begriffe und die doch teils völlig unterschiedliche Anwendung 🙂

    Aber nun gut ich glaube jetzt hat sich das Thema ausdiskutiert 🕶



  • Türlich, hab das "rein-" vergessen.



  • Also es gibt virtuelle Klassen diese funktion dient jedoch nicht dazu das du von einer Klasse erben kannst (das geht immer).
    Wenn eine Klasse virtual deklariert wurde dann verhindert das die Klasse ausversehen 2mal geerbt wurde.
    Bsp:

    Klasse A
    Klasse B
    Klasse C
    Klasse D

    Die Klassen B und C erben von A und D erbt von B und C
    Jetzt enhält D zweimal A(was zu einem kompilerfehler führt).
    Das kann man verhindern indem man B und C virtual von A erben läss.



  • tobZel schrieb:

    Wenn eine Klasse virtual deklariert wurde dann verhindert das die Klasse ausversehen 2mal geerbt wurde.

    Das nennt sich virtuelle Vererbung :p


Anmelden zum Antworten