1
struct A
{
    virtual ~A() { this->f(); }

    virtual void f() {};
};

struct B : A
{
    int* p;

    B() : p(new int) {}

    ~B()
    {
        delete p;
        p = 0;
    }

    void f() override { *p = 0; }
};

int main()
{
    delete new B; // Is it safe?
}

Is it safe to call other virtual methods in virtual destructor?

Jk1
  • 11,233
  • 9
  • 54
  • 64
xmllmx
  • 39,765
  • 26
  • 162
  • 323

2 Answers2

2

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()

Cubbi
  • 46,567
  • 13
  • 103
  • 169
  • It's not undefined if a body has been provided for the pure virtual. – Neil Kirk Aug 27 '13 at 03:19
  • I asked a question to be sure.. http://stackoverflow.com/questions/18456450/is-it-safe-to-call-a-pure-virtual-function-in-an-abstract-constructor-destructor – Neil Kirk Aug 27 '13 at 03:28
1

Note: the OP edited the code to remove the pure virtual part.

With what you have posted, no it is not safe. When you call a virtual function in a constructor or destructor of a class in an inheritance hierarchy, it does not call the most derived function as usual, but calls the function defined within the current class.

In this case, ~A calls A::f() which has no function body, so this is an error. If you provided a body for A::f() (you can do this with pure virtuals, just outside the class definition), then it would be "safe", although whether it does what you want is another matter.

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91