Consider a simple interface/implementation design:
class Base
{
public:
virtual ~Base()
{
// Virtual empty destructor
}
};
class Derived : public Base
{
public:
virtual ~Derived()
{
// Lots of clean up code here
// ...
}
};
With this design, I understand that the following code is safe and valid:
Base* base = new Derived();
delete base; // Both Base::~Base and Derived::~Derived get called
However, imagine if there was a new class:
class DerivedEx : public Derived
{
public:
// No destructor here, relying on default destructor generated by compiler
};
Is DerivedEx “safe”?
For safety, I always assumed that I’d have to implement a virtual empty destructor in DerivedEx. But I’m wondering if this is redundant and unnecessary and whether or not there are any ‘gotchas’ that I’m not aware of.
Yes, it’s still safe.
A destructor is automatically virtual if any base class destructor is virtual. This is true whether you type
~Foo();orvirtual ~Foo();or neither and just allow the compiler to generate the implicitly defined destructor.