Ik heb een goed begrip van de meeste OO theorie, maar het enige dat me erg verwart zijn virtuele destructors.
Ik dacht dat de destructor altijd werd aangeroepen, wat er ook gebeurt en voor elk object in de keten.
Wanneer moet je ze virtueel maken en waarom?
Virtuele destructors zijn nuttig wanneer je een instantie van een afgeleide klasse zou kunnen verwijderen via een pointer naar de basisklasse:
class Base
{
// some virtual methods
};
class Derived : public Base
{
~Derived()
{
// Do some important cleanup
}
};
Hier zult u zien dat ik de destructor van Base'niet als virtueel
heb gedeclareerd. Laten we nu eens kijken naar het volgende knipsel:
Base *b = new Derived();
// use b
delete b; // Here's the problem!
Aangezien de destructor van Base's niet virtueel
is en b
een Base*
is die naar een Derived
object wijst, heeft delete b
ongedefinieerd gedrag:
[In
delete b
], als het statische type van het object dat verwijderd moet worden anders is dan zijn dynamische type, zal het statische type een basisklasse zijn van het dynamische type van het object dat moet worden worden verwijderd en het statische type moet een virtuele destructor hebben of het gedrag is ongedefinieerd.
In de meeste implementaties zal de aanroep van de destructor worden afgehandeld zoals elke niet-virtuele code, wat betekent dat de destructor van de basisklasse zal worden aangeroepen, maar niet die van de afgeleide klasse, wat resulteert in een "resources leak".
Kortom, maak de destructors van basisklassen altijd virtueel
als ze bedoeld zijn om polymorf gemanipuleerd te worden.
Als je het verwijderen van een instantie via een base class pointer wilt voorkomen, kun je de base class destructor protected en nonvirtual maken; door dit te doen zal de compiler je delete
niet laten aanroepen op een base class pointer.
Je kan meer leren over virtualiteit en virtuele base class destructor in dit artikel van Herb Sutter.
Declareer destructors virtueel in polymorfe basis klassen. Dit is punt 7 in Scott Meyers' Effective C++. Meyers vat verder samen dat als een klasse elke virtuele functie heeft, het een virtuele destructor moet hebben, en dat klassen die niet zijn ontworpen om basisklassen te zijn of niet zijn ontworpen om polymorf te worden gebruikt geen virtuele destructors moeten declareren.