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.
 
     
     
     
     
    