Skip to main content
GameDev.net gamedev.net
🔒 Locked

virtual destructors

Started by thedustbustr Jan 7, 2005 at 4:12 PM 4 replies 900+ views
Original Post
thedustbustr
thedustbustr
Are virtual destructors chained like non virtual destructors? IE
struct A{
A() {}
virtual ~A() {}
};
struct B:public A{
B() {}
~B() {}
};
delete (new B);
Will A::~A be called after B::~B is called? [edit] On a related note, SAMS Teach Yourself C++ in 21 Days says that if there is a virtual method, the destructor should almost certainly be virtual. Are there any possible exceptions to this?
Genjix
Genjix

experiment. try replacing B::~B(){} with B::~B() { puts("B::~B()"); } and same with struct A.


BTW: why the use of structs(when you have member functions) in C++?

Qw3r7yU10p!
Qw3r7yU10p!
Quote:
Original post by Genjix

BTW: why the use of structs(when you have member functions) in C++?



Probably because it's an example and there is less to type if you use struct. No need for public:
Qw3r7yU10p!
Qw3r7yU10p!
Quote:
Original post by thedustbustr
On a related note, SAMS Teach Yourself C++ in 21 Days says that if there is a virtual method, the destructor should almost certainly be virtual. Are there any possible exceptions to this?


Well, it's a safety issue. There may be cases where it wouldn't cause a problem, for example if you always call delete on the correct derived type of pointer, or if derived classes don't do anything in their destructors.
Enigma
Enigma
Quote:
Original post by petewood
Quote:
Original post by thedustbustr
On a related note, SAMS Teach Yourself C++ in 21 Days says that if there is a virtual method, the destructor should almost certainly be virtual. Are there any possible exceptions to this?


Well, it's a safety issue. There may be cases where it wouldn't cause a problem, for example if you always call delete on the correct derived type of pointer, or if derived classes don't do anything in their destructors.


To unpack that a bit:

For non-virtual member functions the function to call is determined strictly at compile time:
class X{	public:		~X(){} // non-virtual};class Y	:	public X{	public:		~Y(){} // non-virtual}void func(X* x, Y* y){	delete x; // calls x->~X();	delete y; // calls y->~Y();}

If your pointer actually points to an object of another type then you have problems:
int main(){	X* x = new X(); // X pointer to X	Y* y = new Y(); // Y pointer to Y	func(x, y); // fine	X* x2 = new Y(); // X pointer to Y	Y* y2 = new Y(); // Y pointer to Y	func(x2, y2); // error x2 is not deleted properly - only the X part of it is destoyed (if that), but it is actually a Y object.}

A virtual destructor avoids this error by always calling the appropriate destructor instead of relying on the type of the pointer. You can safely use non-virtual destructors if you can guarantee that the static type of the deleted pointer will always match the dynamic type of object pointed to, i.e. every time you delete an X pointer you can guarantee it points to an X object (not a subclass of X) and every time you delete a Y pointer you can guarantee it points to a Y object (not a subclass of Y) etc.

Enigma
Deyja
Deyja
Expounding further on your original question; destructors are guaranteed to be called in most-derived-first order. (Though they may not be called at all if it's not virtual, they are still technically in order.)

Recall that constructors are called in base-first order. That is, given Class A derived from B, instantiating A results in a call to B() and then to A(...). Base classes must have a default constructor, unless arguments are explicitly supplied in the derived class' member initialization list [IE. A(...) : B(...) {} ]

Destructors are called in exactly the opposite order (assuming they are virtual, of course). When you delete an A, it results in calls to ~A() and ~B(), in that order. This is exactly the opposite of the order of construction.

This means that before a derived class' constructor begins, all base classes are fully constructed, and that all base classes still exist when a derived class' destructor ends! If this wasn't guaranteed - well, things would be a mess. :(

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.