1
votes

It is known that we can use pure virtual destructors, like this:

struct A {
    virtual ~A() = 0;
};
A::~A() {}

struct B : A {};

Because the Standard says in 10.4 [class.abstract] p2

A pure virtual function need be defined only if called ... with (12.4 [class.dtor])

And later in 12.4 [class.dtor] p9

A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined.

What means that the code above is perfectly valid - A::~A may be pure virtual, it is defined, B::~B implicitly calls A::~A.

So far, so good.
And then I read 10.4 [class.abstract] p6:

Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.

But that's exactly what we do here - we call a pure virtual function A::~A from a destructor.

So, isn't there some kind of contradiction?

2
The destructor is a special case, since even if it's pure virtual, it must still have a body (per the standard). The undefined part applies to pure virtual member function (which may not have a definition).StoryTeller - Unslander Monica

2 Answers

3
votes

There is no contraction.

You call the virtual destructor of A from the destructor of B.A destructor is not a member of B.

Standard § 9.3

Member Functions

Functions declared in the definition of a class, excluding those declared with a friend specifier ( 11.3 ), are called member functions of that class

The standard states that there is undefined behavior when there is a virtual call from the abstract class destructor/constructor (which in your case, would be class A) to one of it's own pure virtual member function.

[...] Member functions can be called from a constructor (or destructor) of an abstract class [...];

Your quote says for destructors:

  1. You can call member functions from the destructor of an abstract class
  2. If you call a pure virtual method (with a virtual call) from the destructor of this same abstract class, there is undefined behavior.
-2
votes

UB happens if there is a virtual call (10.3 [class.virtual]).

the effect of making a virtual call (10.3) to a pure virtual function ... is undefined.

But 10.3 [class.virtual] p15 says that

Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism.

It seems that implicit destructor call has an explicit qualification.
At least compiler definitely doesn't do a virtual call there.