Is it safe to call a pure virtual function in an abstract constructor / destructor if it has a body?

Without the line labeled BODY, I know this is unsafe. But with this, is it safe?

struct A { virtual ~A() { f(); } virtual void f() = 0; }; void A::f() {} // BODY struct B : A { void f() {} }; int main() { delete new B; } 

Working example: http://ideone.com/9bRZ3i

+3
source share
2 answers

If you want to bypass the virtual dispatch and call the body of the function that you defined, you must qualify the function name:

 virtual ~A() { A::f(); } // OK. 

Otherwise, the call initiates a virtual dispatch, but only to the base class, because the object of the derived type is already destroyed before its bases.

C ++ 11 §12.7 / 4 directly solves your question:

Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a virtual function is called directly or indirectly from a constructor or from a destructor, including when constructing or destroying non-static elements of these classes, and the object to which the call is applied is the object (name it x) for construction or destruction, the called function is the final redefinition in the class of constructors or destructors and does not override it in a more derived class. If the call to a virtual function uses explicit access to a class member (5.2.5), and the expression of the object refers to the full object x or one of the subobjects of the base class of objects, but not to x or one of its subobjects of the base class, the behavior is undefined.

However, §10.4 / 6 forbids this to be done with a pure virtual function:

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

So this is UB.

The effect of “pure virtual” is to hide the definition of a function from virtual search. You will never achieve the definition of a pure virtual function from a dynamic dispatch call, except possibly as an undefined behavior effect.

+4
source

No, this is not safe. Although constructor A (or destructor) executes the object, it has type A , and (no more) object B A call to f() will try to send (as before) a pure virtual function and invoke undefined behavior. Most implementations will catch this and terminate the application with an error message that indicates that a pure virtual function has been called.


After editing:

The fact that there is a definition for a pure virtual function means that it is legal to call it without going through the virtual dispatch. It is still illegal to call a pure virtual function using dynamic dispatch. But you can rewrite the constructor like this:

 A::~A() { A::f(); } // qualification disables dynamic dispatch 

Without dynamic sending, the code becomes valid.

+7
source

Source: https://habr.com/ru/post/952578/


All Articles