Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Virtual keyword in multiple layer inheritance

I have an inheritance chain, where class A publicly inherits from class B, which in turn publicly inherits from class C. The destructor of class C is marked as "virtual". Is there any objection against marking the destructors of class B and A as virtual? Or is there a performance/memory penalty to pay in these situations?

like image 226
Frank Avatar asked Jan 02 '23 02:01

Frank


2 Answers

If the base class destructor is marked virtual then the Derived class destructor is implicitly virtual as well, you don't need to specify it as virtual explicitly. There's no performance or memory penalty

So in your example, if C has a virtual destructor B and A inherits the "virtual-ness" of destructor

like image 55
P0W Avatar answered Jan 12 '23 02:01

P0W


Yes, there is. The compiler creates and manages a vtable for such a hierarchy as soon as there is at least one virtual member function (special or ordinary).

However, as the following situation is a route to UB

class Base {};

class Derived : public Base {};

Base *b = new Derived{};

delete b; /* Undefined behavior, destructor of B is not virtual. */

it is a common automatism to change the above Base class to

class Base {
  public:
    virtual ~Base() = default;
};

and now any derived class can safely be deleted through the virtual destructor of B.

There are situations though in which an inheritance hierarchy is supposed to extend class functionality without use cases with references to a Base instance. Then, you should go with a protected, non-virtual destructor. The base class can hence only be destroyed from within derived classes:

class Base {
  protected:
    ~Base() = default;
};

disallows this snippet

Base *b = new Derived{};

delete b; /* Error, ~Base() is protected. */

but allows for

Derived *d = new Derived{};

delete d; /* That's fine.*/

and hence saves the class usage from undefined behavior while the compiler won't generate a vtable for you, allowing for maximum performance. This is a common technique e.g. in policy based design.

like image 42
lubgr Avatar answered Jan 12 '23 04:01

lubgr