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?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With