Jump to content
  • Advertisement
Sign in to follow this  
thedustbustr

virtual destructors

This topic is 5060 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Advertisement

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++?

Share this post


Link to post
Share on other sites
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:

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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. :(

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!