Ein virtueller Destructor ist ein Destructor, der im Basisklasse mit dem Schlüsselwort virtual deklariert ist. Dies stellt sicher, dass der Destructor der abgeleiteten Klasse aufgerufen wird, wenn ein Objekt über einen Zeiger auf die Basisklasse gelöscht wird.
class Base { public: virtual ~Base() { /* ... */ } }; class Derived : public Base { public: ~Derived() override { /* ... */ } }; Base* ptr = new Derived(); delete ptr; // Beide Destructoren werden aufgerufen
Ohne virtuellen Destructor kann das Verhalten inkorrekt sein – der Destructor der abgeleiteten Klasse wird nicht aufgerufen, was zu Ressourcenlecks führt!
Sollte der Destructor virtuell deklariert werden, wenn in Ihrer Basisklasse keine virtuellen Funktionen vorhanden sind?
Antwort: Ja, wenn von der Klasse Vererbung mit Löschung über einen Zeiger auf den Basistyp erwartet wird. Selbst wenn es keine anderen virtuellen Funktionen gibt, ist die Virtualität des Destructors erforderlich, um die korrekte Löschung der Nachkommen sicherzustellen.
class Shape { public: virtual ~Shape() {} };
Geschichte 1
In einem großen Projekt einer Grafikbibliothek traten beim Löschen von Zeichenobjekten über einen Zeiger auf die Basisklasse OpenGL-Ressourcenlecks (Puffer, Texturen) auf – die entsprechenden Freigaben befanden sich in den Destructoren der abgeleiteten Klassen, die jedoch nicht aufgerufen wurden.
Geschichte 2
In einer Netzwerkbibliothek für das TCP-Protokoll wurde beim Löschen von Sitzungen der Destructor der Nachfolger, die über eine gemeinsame Basisschnittstelle verwaltet wurden, nicht aufgerufen. Dies führte zu massiven Socket-Blockaden und Erschöpfung der Descriptorlimits.
Geschichte 3
In einem eingebetteten System in C++ führte ein falsch deklarierter (nicht-virtueller) Destructor der Basisklasse zu einem Speicherleck für systemeigene Ressourcen der Eingabe-Output-Controller, wodurch Geräte nach mehreren Treiberaktualisierungsschleifen ausfielen.