====== Virtuelle Destruktoren ======
Wenn eine Klasse virtuelle Methoden enthält, sollte sie zusätzlich auch den Destruktor virtuell beschreiben.
Nehmen wir folgendes Szenario an:
#include
#include
class Node
{
public:
Node * Next;
Node * Prev;
char * UserData;
Node()
: Next( NULL )
, Prev( NULL )
{
UserData = new char[500];
}
~Node()
{
printf( "Destruiere Node - loesche UserData\n" );
delete [] UserData;
}
};
class MyNode : public Node
{
public:
char * MoreData;
MyNode()
{
MoreData = new char[500];
}
~MyNode()
{
printf( "Destruiere MyNode - loesche MoreData\n" );
delete [] MoreData;
}
};
void deleteNode( Node * toDelete )
{
delete toDelete;
}
int main( void )
{
MyNode *myNode1, *myNode2;
myNode1 = new MyNode;
myNode2 = new MyNode;
deleteNode( myNode1 );
delete( myNode2 );
return EXIT_SUCCESS;
}
Dieses Programm ist nicht objektorientiert, die Funktion ''deleteNode'' erhält einen Pointer auf ''Node'' und gibt diesen frei. Da der Destruktor nicht virtuell ist, also nicht Objekttyp-Abhängig ist, ruft C++ den Destruktor entsprechend des Datentypes von ''toDelete'' - und das ist Node, nicht MyNode.
Schauen wir uns die Ausgaben an:
Destruiere Node - loesche UserData
Destruiere MyNode - loesche MoreData
Destruiere Node - loesche UserData
Obwohl die Funktion deleteNode einen Zeiger auf ein Objekt der Klasse ''MyNode'' erhält, geht Information, dass es sich um ein MyNode handelt verloren und C++ sieht in ''deleteNode'' nur noch den Zeiger auf ein ''Node'' und ruft den Konstruktor, der für ''Node'' gilt. Da der Destruktor nicht virtual ist, wird Node::~Node() gerufen. Dies ist aber ja nicht gewünscht, zuerst muss ja der Destruktor MyNode::~MyNode gerufen werden, damit auch der Member ''MoreData'' freigegeben wird und dieser Destruktor anschließend den Destruktor seiner Basisklasse ruft.
Um das einzurichten, erklären wir den Destruktor von ''Node'' für virtual:
virtual ~Node()
{
printf( "Destruiere Node - loesche UserData\n" );
delete [] UserData;
}
Nun weiß delete, dass es den Destruktor in der virtual Table suchen muss und findet dort den Destruktor von ''~MyNode''.
Somit erhalten wir das richtige Ergebnis:
Destruiere MyNode - loesche MoreData
Destruiere Node - loesche UserData
Destruiere MyNode - loesche MoreData
Destruiere Node - loesche UserData