Dies kann passieren, weil Parent
möglicherweise keinen virtuellen Destruktor hat. Da Sie eine Parent*
(die Basisklasse) für eine dynamisch zugewiesene abgeleitete Klasse Child
erstellen, führt das Löschen der Parent*
, die keinen virtuellen Destruktor hat, zu undefiniertem Verhalten, führt jedoch in der Regel dazu, dass die abgeleitete Klasse nicht zerstört wird.
Von Scott Myers - Effective C++ Third Edition:
... wenn wir Basisklasse Zeiger mit einem nicht-virtuellen Destruktor löschen, Ergebnisse nicht definiert sind. In der Regel tritt zur Laufzeit auf, dass der abgeleitete Teil des Objekts niemals zerstört wird. Dies ist eine hervorragende Möglichkeit, Ressourcen zu verlieren, Datenstrukturen zu beschädigen und viel Zeit mit einem Debugger zu verbringen. Also sollte jede Klasse mit virtuellen Funktionen fast sicher einen virtuellen Destruktor haben.
class Parent{
};
class Child:public Parent{
public:
Child() : str("Child") {}
~Child() { std::cout << str << std::endl;};
std::string str;
};
int main(){
Parent *ptr=new Child();
delete ptr; // undefined behaviour: deleting a Base* to a Derived object where the Base has no virtual destructor
}
Sie können dieses Problem beheben, indem Parent
‚s destructor machen virtual
:
class Parent{
public:
virtual ~Parent() {} // Will call derived classes destructors now as well
};
class Child:public Parent{
public:
Child() : str("Child") {}
~Child() { std::cout << str << std::endl;};
std::string str;
};
int main(){
Parent *ptr=new Child();
delete ptr;
// Child::~Child() has now been called.
}
When to use virtual destructors? Sie, welche wahrscheinlich erklärt es besser als ich
bearbeiten: Vielen Dank an die @ascheppler (in den Kommentaren der Frage), Kommentatoren unten und die Antwort auf die verknüpfte Frage, ich habe die Antwort auf die Wette aktualisiert widerlegen, dass dies ein undefiniertes Verhalten ist. In meiner Hast habe ich es nicht erwähnt, und erwähnte nur die typische Verhalten
Hat Parent einen virtuellen Destruktor? Sie löschen ein Parent *, wenn der Destruktor nicht virtuell ist, ruft er nicht Child :: ~ Child() auf. – Tas
Hinweis: Wenn "Parent" keinen virtuellen Destruktor hat, ist "delete" Undefined Behavior, was schlimmer ist als ein Speicher Leck. – aschepler