Archived

This topic is now archived and is closed to further replies.

alnite

why do we have virtual destructors?

Recommended Posts

alnite    3438
virtual functions are used to define a unique behavior for each inherited (child) classes, but what about virtual destructors? does it matter on how we uninitialize member data so that the destructor need to be virtual? i still have no clue about it. can somebody please explain it to me?
500

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
lets say we have a class

class Parent
{
public:
Parent() { MyData = new int[100]; }
~Parent() { delete [] MyData; }

private:
int* MyData;
};

everything works fine, as long as there are no subclasses, but if there were and the destructor is not virtual, it won''t be called.

Share this post


Link to post
Share on other sites
So that each class can have its own individual destructor.

If you have data that you need to clean up (memory allocated off the heap), the actual destructor varies depending on what all you need to free. You could have a base class that frees up a certain amount of memory, and another class that inherits the base class, but needs to clean up more stuff.

Share this post


Link to post
Share on other sites
alnite    3438
quote:
Original post by The Reindeer Effect
So that each class can have its own individual destructor.


So, the dtor for each class is not automatically called?
Let''s say I have the following class hierarchy:

Animal
|
Cat
|
My Cat

When an object of My Cat is uninstantiated, the dtor of My Cat is called. Then, Cat''s dtor is called, and then finally Animal''s dtor. Are you saying that the compiler won''t call Cat''s dtor and Animal''s dtor unless their dtors are virtual?


500

Share this post


Link to post
Share on other sites
Beer Hunter    712

  
#include <iostream>

using namespace std;

class Base {
public:
Base() { cout << "Base" << endl; }
~Base() { cout << "~Base" << endl; }
};

class Derived: public Base {
public:
Derived() { cout << "Derived" << endl; }
~Derived() { cout << "~Derived" << endl; }
};

int main()
{
cout << "Test 1:" << endl;
Derived* d = new Derived;
delete d;
cout << endl;

cout << "Test 2:" << endl;
Base* b = new Derived;
delete b;
cout << endl;

cout << "Press enter..." << endl;
cin.get();
}
Examine the output of the second test case carefully. Then make the destructors virtual and run it again.

Share this post


Link to post
Share on other sites
Fruny    1658
quote:
Original post by alnite
When an object of My Cat is uninstantiated, the dtor of My Cat is called. Then, Cat''s dtor is called, and then finally Animal''s dtor. Are you saying that the compiler won''t call Cat''s dtor and Animal''s dtor unless their dtors are virtual?



If you have an Animal* that is pointing to a MyCat object and the Animal class doesn''t have a virtual destructor, the effect of calling delete on that pointer is undefined.

Which means that, when writing their compiler, compiler implementers are allowed to assume that this will never happen, don''t have to check nor special case for it.

So, when you do write something like that, your code is actually falling through the cracks in the compiler. The results might make sense (only call Animal''s destructor), because of the way the code is generated, but there is absolutely no guarantee it will stay the same from one compiler to another, or even from one *build* to another.

For all you know, the behaviour might change with the phase of the moon.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]

Share this post


Link to post
Share on other sites