TICS Coding Standard Viewer 
TIOBE Software Quality Framework
Print-friendly version
©TIOBE Software www.tiobe.com
C++ Coding Standard

Rule:  OOP#013Checked automatically with code checker

Synopsis:A base class destructor should be either public and virtual, or protected and non-virtual
Severity Level:1
Category:Object Oriented Programming


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.

Example, bad

struct Base {  // BAD: implicitly has a public non-virtual destructor
    virtual void f();

struct D : Base {
    string s {"a resource needing cleanup"};
    ~D() { /* ... do some cleanup ... */ }
    // ...

void use()
    unique_ptr p = make_unique();
    // ...
} // p's destruction calls ~Base(), not ~D(), which leaks D::s and possibly more

Note A virtual function defines an interface to derived classes that can be used without looking at the derived classes. If the interface allows destroying, it should be safe to do so.

Note A destructor must be non-private or it will prevent using the type:

class X {
    ~X();   // private destructor
    // ...

void use()
    X a;                        // error: cannot destroy
    auto p = make_unique();  // error: cannot destroy

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.

Literature References:
C++ Core Guidelines Rule C.35