I've been studying up on virtual destructors and how they work and I wrote this little program. I've been adding and removing the word "virtual" on lines 9, 16, and 23 to see what happens.
#include <iostream>
using namespace std;
class a
{
public:
a(){cout << "a::a()" << endl;}
virtual ~a(){cout << "a::~a()" << endl;}
};
class b: public a
{
public:
b(){cout << "b::b()" << endl;}
virtual ~b(){cout << "b::~b()" << endl;}
};
class c: public b
{
public:
c(){cout << "c::c()" << endl;}
virtual ~c(){cout << "c::~c()" << endl;}
};
int main()
{
{
a* x = new c();
delete x;
}
return 0;
}
Here are my findings...
- When "virtual" is on all the lines, all destructors are called. Makes sense to me.
- When "virtual" is on none of the lines, only a's destructor is called. Also makes sense to me.
- When a's destructor is not virtual and either b's or c's IS virtual, the program crashes. I'm not sure why this one happens.
- When a's destructor virtual and b's and c's destructors are not virtual, all three destructors are called. This one is really puzzling me. I thought that you started at the base destructor and stopped after the first non-virtual destructor. In this case, b's destructor would not be virtual, so c's should not ahve been called? But it was called.
Finally, is there ever a time when you would not want to define all three destructors as virtual? If b and c had no dynamic memory to delete, it would cause no problems to not call the destructors, but at the same time, what would the harm be?
Any guidance on what that magical word "virtual" does in these cases would be appreciated, particularly what is happening in list items 3 and 4 would be appreciated.