Virtuelle Destruktoren
-
Speicherlöcher ist gut
wenn du ein Objekt einer abgeleiteten Klasse über einen Basisklassenzeiger löschst, und es gibt keinen virtuellen Destruktor, ist das Verhalten undefiniert.
-
evilissimo schrieb:
Sie werden für alle Klassen verwendet die an andere vererbt werden.
Nicht zwangsläufig, zB bei non-public Vererbung.
-
Auch bei public-Vererbung könnte der Destruktor non-virtual sein, wenn man ihn dafür protected macht.
Aber ich glaube darauf kommt es dem OP garnicht so sehr an.

-
Beispiel:
struct Base { /* virtual */ ~Base(); } struct Derived : public /* / protected / private */ Base { Derived() { AcquireResource(); } ~Derived() { ReleaseResource(); } } int main() { Base * base = new Derived; // [1] delete base; // [2] }in [1] wird Derived::Derived() aufgerufen.
ist der Base-Destruktor nicht virtuell, wird in [2] Derived::~Derived nicht aufgerufen.
-
Allerdings bekommst du mit protected oder private keinen Zeiger auf Base.
-
das stimmt

Es ließen sich aber trotzdem ein paar Szenarien aus der Luft greifen..
-
zu dem thema hätte ich auch ne frage, nur interessehalber:
class FooBase { bar *zeiger1; public: FooBase() { zeiger1 = new bar(); } virtual ~FooBase() { delete zeiger1; } }; class Foo { bar* zeiger2; public: Foo() { zeiger2 = new bar(); } ~Foo() { delete zeiger2; /*delete zeiger1*/ //ja oder nein?? } };ohne getestet zu haben... ersetzt der neue Dekonstruktor den alten vollständig oder werden beide aufgerufen? Beim Konstruktor wird ja auch immer der der Basisklasse aufgerufen. Andererseits...
geloescht
-
Ja, der wird auch aufgerufen, sonst wären in bestimmten Situationen Resource-Leaks unvermeidbar.
Beim Konstruieren werden zuerst alle Basisklassen konstruiert, dann alle Member und dann der Konstruktor der Klasse aufgerufen.
Beim zerstören geht es genau umgekehrt. Erst der Destruktor der abgeleiteten Klasse, dann die Destruktoren aller Member (ebenfalls in umgekehrter Reihenfolge der Konstruktion) und anschließend die Destruktoren der Basisklassen (auch wieder in umgekehrter Reihenfolge der Konstruktion).MfG Jester
-
also obwohl sich das virtual mehr oder weniger "vererbt". danke, das wollte ich wissen

geloescht
-
Genau. Das virtual sorgt dafür, daß auch auf der richtigen Ebene (nämlich ganz unten) mit dem Zerstören angefangen wird.
-
und das "delete zeiger1" sollte auf jeden Fall aus dem Destruktor von foo rausbleiben. Denn der Destruktor von fooBase ruft sonst noch einmal delete auf und da der Zeiger dann weder NULL ist noch auf eine gültige Adresse verweist ist das verhalten dann schlichtweg undefiniert.
(Zu dem Stichwort mal ein nettes Zitat von Scott Meyers: "...nicht definiert. Das heißt, Ihre Compiler könnten jeden beliebigen Code generieren, den sie wollen - Code zum Formatieren Ihrer Festplatte, um zweideutige Emails an Ihren Chef zu schicken, der Konkurrenz den Quellcode Ihrer Programme zu faxen oder was auch immer.")