2

Common wisdom is that if you can make a class abstract by having a pure virtual destructor.

To quote Herb Sutter:

All base classes should have a virtual destructor (see your favourite C++ book for the reasons). If the class should be abstract (you want to prevent instantiating it) but it doesn't happen to have any other pure virtual functions, a common technique to make the destructor pure virtual:

However the following code compiles for me with GCC and VC:

#include <iostream>

struct base {
    virtual ~base() = 0;
};

base::~base() { std::cout << "base destructor\n"; }

struct derived : base { };

int main() {
    derived d;
}

Has something changed in C++11 that I'm not aware of?

BTW the motivation to this question is an answer I gave five years ago and was suddenly challenged by a commenter.

Community
  • 1
  • 1
Motti
  • 110,860
  • 49
  • 189
  • 262
  • Why should it not compile? You are instantiating a derived object, not a base object. And only your base is abstract, because your derived class has the default destructor. – Horstling Aug 31 '14 at 13:29
  • `by having a pure virtual constructor` => `by having a pure virtual destructor`? – Gluttton Aug 31 '14 at 13:43
  • @Horstling it should not compile since its base class has a pure virtual method (if `base` had a `virtual void f() = 0` then you could not instansiate an instance of `derived`) – Motti Aug 31 '14 at 13:52
  • You don't think derived had a dtor? Or are you saying that since base's dtor is abstract derived must automatically be? – H Walters Aug 31 '14 at 13:56
  • @HWalters good point, so you're saying that the compiler generated dtor is fulfilling the required override? I haven't thought of that (perhaps you should add this as an answer) – Motti Aug 31 '14 at 13:59
  • No... see my correction for the answer. Edit: I'll post an answer if the author of the current one doesn't correct in a few minutes. – H Walters Aug 31 '14 at 14:01
  • @Motti: You are probably confused by the expectation that overriding non-pure method must have the same name and signature. That applies to "regular" methods only. Destructors are special. Derived's destructor always overrides base destructor even though it appears to be named differently. That's how it has always been. How would the entire idea of virtual destructor work, if that wasn't the case? – AnT stands with Russia Aug 31 '14 at 14:07
  • @AndreyT, no, I just didn't expect the compiler to implicitly generate a destructor for `derived`. – Motti Aug 31 '14 at 14:09
  • 1
    @Motti: Since C++98 destructor have always been implicitly declared as non-pure member (in the absence of user-declared one). – AnT stands with Russia Aug 31 '14 at 14:11
  • 2
    The purpose of the pure virtual destructor is not to make the above code illegal. It is to make this code illegal: `base b;` – Raymond Chen Aug 31 '14 at 14:24

1 Answers1

3

The derived class has an implicitly defined (compiler-provided) virtual destructor, which is not pure and which overrides the base destructor. For this reason derived is not an abstract class. It can be instantiated.

This has nothing to do with C++11. That's how it has always been since C++98. Making a base class destructor pure virtual is a way to make that and only that class abstract. The compiler-provided destructors in derived classes will be non-pure virtual, which will automatically "cancel out" that abstractness in those classes (assuming no other pure virtual methods were inherited from the base).

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Derived's destructor doesn't override base's. Think about what override means. – H Walters Aug 31 '14 at 13:59
  • @H Walters: Er... Yes, derived destructor does override virtual base destructor. And that's exactly what override means. – AnT stands with Russia Aug 31 '14 at 14:02
  • mea culpa... I was referring to the fact that dtor's chain rather than hide, but given the standard describing dtor's as overriding, it wins. – H Walters Aug 31 '14 at 14:18
  • ...of course that has to be true. Chaining behavior's irrelevant... override refers to behaviors of calls through the base. That's what I get for trying to overthink this. – H Walters Aug 31 '14 at 14:28