It is safe if you know the rules, and the rules say that within a destructor, the dynamic type of the object is the class whose destructor is executing.
While B::~B()
is executing, the type of the object is B
(and if you call f()
then, you'll get dispatched to B::f()
While A::~A()
is executing, the type of the object is A
, and if you call f()
then, you get undefined behavior per §10.4[class.abstract]/6
Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined
Or, as clang++ reports it,
test.cc:5:20: warning: call to pure virtual member function 'f'; overrides of 'f' in subclasses are not available in the destructor of 'A'
virtual ~A() { this->f(); }
^
test.cc:7:5: note: 'f' declared here
virtual void f() = 0;
^
1 warning generated.
EDIT: OP edited pure virtual out.. so, then, while A::~A()
is executing, virtual call to f()
gets dispatched to A::f()