warnung: virtueller destruktor benötigt?



  • hallo,
    hab folgendes problem

    class A
    {
        public:
            A(){};
            ~A(){};
    };
    
    class B :
        virtual public A
    {
        public:
            virtual void b() = 0;
    };
    
    class C :
        virtual public B
    {
        public:
            C(){};
            void b(){};
    };
    
    int main()
    {
        A a;
        C c;
        return 0;
    };
    

    der compiler von Code::Blocks warnt mich nun das B und C einen virtuellen Destruktor benötigen. Tatsächlich reicht ein virtueller Destruktor bei B aus, aber was mich viel mehr interessiert ist, warum ich überhaupt die Warnung bekomme. Es muss etwas mit der virtual Vererbung zu tun haben, denn wenn ich das virtual weglasse brauche ich das nicht mehr machen. allerdings kann ich bei meinen tatsächlichen klassen dann das virtual nicht weglassen.
    Danke schonmal im voraus.



  • Hallo,

    du musst eigentlich bei allen Funktionen (+ Destruktor)
    die du Vererben willst ein virtual davor setzen

    also eigentlich auch bei ~A()

    Gruß Simon



  • ich hatte diese blöde warnung auch schon gelegentlich an unpassenden stellen. ich habe beschlossen, sie auszumachen, irgend einen compilerschalter dafür wirds schon geben.



  • Klassen die virtuell erben und/oder neue virtuelle Funktionen deklarieren (neu = nicht geerbt in dem Fall) sind normalerweise als polymorphe Basisklassen gedacht. Sonst hätte es ja keinen Zweck, die Vererbung bzw. die Funktion virtuell zu machen. Und polymorphe Basisklassen sollten nunmal im Normalfall einen virtuellen Destruktor haben, damit polymorphes delete möglich ist. (delete auf einen Basisklassenpointer erzeugt undefiniertes verhalten, wenn der Dtor der Basisklasse nicht virtuell ist).



  • ich rede nicht von virtual funktionen sonder davon das ich A bzw B virtual vererbe. wenn ich den destruktor virtual setze, bedeutet das doch nur das er spät gebunden wird.



  • @FreakyBKA

    Sie sollten Ihre Aufgaben in OOP lieber allein lösen. Nehmen Sie sich doch einfach ein gutes CPP-Buch, dann klappt es auch mit der Abnahme!



  • @guterRat: hää? check ich nicht!



  • das heißt also, dass ich meinen Destruktor bei A auch virtual machen muss? aber wird der dann trotzdem noch ausgeführt, wenn ich den Destruktor in B oder C aufrufe? Und in B muss ich dann auch noch einen virtual Destruktor reinpacken? eigentlich gibts in B nichts sinnvolles was der Destruktor ausführen soll. nur der Destruktor von A hat eine spezielle Aufgabe und der von C.



  • FreakyBKA schrieb:

    ich rede nicht von virtual funktionen sonder davon das ich A bzw B virtual vererbe.

    Der Compiler redet aber von virtuellen Funktionen 🙂

    Da B eine virtuelle Methode enthält, sollte B auch einen virtuellen Desktruktor enthalten. Ich bin mir sogar ziemlich sicher, dass die Compilermeldung genau das aussagt (class with virtual functions but non-virtual destructor).

    Die Begründung wurde schon genannt: Damit ein "delete object" mit decltype(object) == B auch dann definiert ist, wenn object auf ein C zeigt.



  • alles klar, jetzt hab ichs verstanden.
    wenn ich allerdings den Dtor in A schon virtual mache brauche ich in B keinen mehr einfügen da dieser ja schon den von A erbt und soweit ich weiß das virtual mit vererbt wird. sehe ich das richtig? zumindest spuckt mir der compiler keine warnung mehr aus, wenn ich nur in A einen virtual Dtor schreibe und den in B weglasse.


  • Administrator

    FreakyBKA schrieb:

    wenn ich allerdings den Dtor in A schon virtual mache brauche ich in B keinen mehr einfügen da dieser ja schon den von A erbt und soweit ich weiß das virtual mit vererbt wird. sehe ich das richtig?

    Jein, der Destruktor wird nicht vererbt, jedes Objekt hat automatisch einen eigenen Destruktor, auch wenn man ihn nicht angibt. Wenn der Destruktor in der Basisklasse allerdings virtual ist, dann sind auch alle Destruktoren virtual , welche zu einer von der Basisklasse abgeleiteten Klasse gehören. Also auch die automatisch vom Compiler erstellten Destruktoren.

    Grüssli



  • wo wir gerade dabei sind, habe ich gerade noch ein anderes problem entdeckt, wo ich nicht weiß warum man das so machen muss, vllt kann mir das ja jemand erklären.

    class A
    {
        public:
            A(){};
            virtual ~A(){};
    };
    
    template<class t>
    class B :
    	virtual public A
    {
    	public:
    		class BB
    		{
    			private:
    				t b;
    			public:
    				void bb(){};
    		};
    };
    
    template<class t>
    class D
    {
    	public:
    		t _t;
    };
    
    template<class t>
    class C :
    	virtual private B<t>
    {
    	private:
    	public:
    		using B<t>::BB;
    		C(){};
    		~C(){};
    		void c()
    		{
    			D<typename BB> d; // Fehler, hier muss "typename B<t>::BB" rein, aber warum?
    			d._t.bb();
    		};
    };
    

    gibt es irgendeine möglichkeit die subklasse BB von B in C direkt verfügbar zu machen mit using gehts offensichtlich nicht.

    grüße


  • Administrator

    Das Problem hatten wir erst gerade:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-241013.html

    Gilt auch für "Subklassen".

    Grüssli



  • alles klar, besten dank.
    @Dravere: bist echt immer wieder eine große hilfe


Anmelden zum Antworten