2

Say I have two base classes,

struct A {}; 
struct B {}; 

and a derived one that uses multiple inheritance

struct D : A, B {}; 

If my use scenario goes something like this:

A *obj = new D; 

i.e. I'll never use the B base class to refer to the derived object, do I have to make the destructor of both bases virtual? I'm currently declaring the destructor of B as protected to forbid other users from doing this, but is it enough?

What about the destructor of D?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Lorah Attkins
  • 5,331
  • 3
  • 29
  • 63
  • No, but you should. – Niels Keurentjes Jan 17 '17 at 23:51
  • 3
    If you're never going to refer to `D` as a `B` you might be interested in [`protected` or `private` inheritance.](http://stackoverflow.com/questions/860339/difference-between-private-public-and-protected-inheritance) – jaggedSpire Jan 17 '17 at 23:53
  • 2
    To quote the mighty Scott Meyers: *...declare a virtual destructor in a class if and only if that class contains at least one virtual function*. –  Jan 17 '17 at 23:54
  • @NielsKeurentjes Why? With `B`'s destructor being protected, you can't delete a `D` instance through `B*`, so in the example above only `A`'s destructor needs to be `virtual` – Praetorian Jan 17 '17 at 23:54
  • 1
    @RawN on the other hand, Herb Sutter says, "A base class destructor should be either public and virtual, or protected and nonvirtual." – Brian Bi Jan 17 '17 at 23:55
  • 2
    @Brian so, when you combine the rules of thumb: If base class has virtual functions, then make the destructor public and virtual, otherwise make the destructor protected and nonvirtual. – eerorika Jan 18 '17 at 00:01
  • @Praetorian for the reason Brian quotes. Any public non-virtual destructor is a maintenance risk. I wasn't sure from the wording of the question he was intent on keeping it protected. – Niels Keurentjes Jan 18 '17 at 00:02
  • Be careful with blindly applying any rule. For example, in Microsoft's COM technology, interface classes have virtual functions and no virtual destructor. It would be an error to try to delete a pointer to a COM interface. – Cheers and hth. - Alf Jan 18 '17 at 10:54
  • @Cheersandhth.-Alf Technically, that wouldn't be blindly applying a rule, but rather blindly assuming that others have followed the rule. – eerorika Jan 18 '17 at 11:01

1 Answers1

7

It is not necessary for B's destructor to be virtual as long as a B* is never used to delete derived objects. See [expr.delete]/3:

... if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.

In this case the "static type" is the type T cv where the operand to delete has type T cv *. So the requirements in your case are imposed on A, not on B.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312