Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a use for making a protected destructor virtual?

/*Child is inherited from Parent*/
class Parent {  
  public:  
    Parent () //Constructor
    {
        cout << "\n Parent constructor called\n" << endl;
    }
  protected:
    ~Parent() //Dtor
    {
        cout << "\n Parent destructor called\n" << endl;
    }
};

class Child : public Parent 
{
  public:
    Child () //Ctor
    {
        cout << "\nChild constructor called\n" << endl;
    }
    ~Child() //dtor
    {
        cout << "\nChild destructor called\n" << endl;
    }
};

int main ()
{
    Parent * p2 = new Child;          
    delete p2;
    return 0;
}

If I make Parent's destructor virtual, then I obtain an error, so what is the purpose of making a protected destructor virtual?

like image 375
tusharfloyd Avatar asked Jan 23 '12 10:01

tusharfloyd


People also ask

When to use a non virtual protected destructor?

If the class does not need to be polymorphic, but still needs to allow its interface to be inherited, use a non-virtual protected destructor. Such a class can never be destroyed through a pointer, avoiding silent leaks due to slicing. This technique especially applies to classes designed to be private base classes.

Why do we need a virtual destructor in a class?

A class designed to be used polymorphically at run-time (through a pointer to the base class) should declare the destructor virtual. This allows the derived parts of the object to be properly destroyed, even when the object is destroyed through a pointer to the base class.

Why do destructors need to be protected?

If the destructor is protected, then calling code cannot destroy through a base class pointer and the destructor does not need to be virtual; it does need to be protected, not private, so that derived destructors can invoke it.

How to fix “deleting a derived class with a non-virtual destructor”?

Deleting a derived class object using a pointer of base class type that has a non-virtual destructor results in undefined behavior. To correct this situation, the base class should be defined with a virtual destructor. For example, following program results in undefined behavior.


4 Answers

There's an entry in the C++ Core Guidelines dedicated to this specific subject:

C.35: A base class destructor should be either public and virtual, or protected and nonvirtual

Reason To prevent undefined behavior. If the destructor is public, then calling code can attempt to destroy a derived class object through a base class pointer, and the result is undefined if the base class’s destructor is non-virtual. If the destructor is protected, then calling code cannot destroy through a base class pointer and the destructor does not need to be virtual; it does need to be protected, not private, so that derived destructors can invoke it. In general, the writer of a base class does not know the appropriate action to be done upon destruction.

So, the destructor doesn't need to be virtual if it's protected. However, there is an exception:

Exception We can imagine one case where you could want a protected virtual destructor: When an object of a derived type (and only of such a type) should be allowed to destroy another object (not itself) through a pointer to base. We haven’t seen such a case in practice, though.

So, to sum up, in practice a protected destructor does not need to be virtual.

like image 187
Alexandre Hamez Avatar answered Oct 09 '22 14:10

Alexandre Hamez


Yes, if you intend to do delete this in class Parent member functions which is very common when implementing IUnknown::Release() in COM objects.

like image 41
sharptooth Avatar answered Oct 09 '22 15:10

sharptooth


Just to give one example: Say you have an base class which implements reference counting. You have an addRef and a release method and you want your object to be destroyed, if (and only if) the internal counter reaches zero through a call to release.

So, first you want your destructor protected (since you only want to destroy the object from within release).

If you plan to derive from your class, you also want to have your destructor virtual, since you need a virtual destructor whenever you want to destroy a child object through a pointer to a base class (thanks @sharptooth for the hint ...)

like image 23
MartinStettner Avatar answered Oct 09 '22 13:10

MartinStettner


protected: Base::~Base(); should be virtual at least if you (plan on) deleting any objects derived from Base within Base or a derived class of Base.

like image 42
bitmask Avatar answered Oct 09 '22 14:10

bitmask