Virtual methods from constructor / destructor in C++

I was reading the following discussion on the Chromium developers group: Virtual dispatch doesn’t work (as you might expect) in destructors! which documents a problem that arised during the development of a specific piece of code in Chromium. What it says is that virtual methods called from inside constructors or destructors are not dispatched to their intended final destination. Instead of that, they are dispatched to the declaration inside the object being constructed or destructed at the moment. A much more detailed explanation is given by Scott Meyers in the following article: Never Call Virtual Functions during Construction or Destruction

Below, I give as proof of concept a piece of code that exhibits this behaviour.

#include <stdio.h>

class A {
 public:
  void call_virtual();
  virtual ~A();
  virtual void cleanup() = 0;
};

class B : public A {
  virtual void cleanup();
};

void A::call_virtual() {
  printf("A: call_virtual\n");
  cleanup();
}

A::~A() {
  printf("A: destructor\n");
  call_virtual();
}

void B::cleanup() {
  printf("B: cleanup\n");
}

int main() {
  {
    B b;
    b.call_virtual();
  }
  return 0;
}

Executing the above program yields the following output:

A: call_virtual
B: cleanup
A: destructor
A: call_virtual
pure virtual method called
Aborted

It is clear that during the call of A’s destructor an attempt is made to call A’s virtual method, which is defined as pure so a runtime error occurs terminating our program’s execution. Note that we call the virtual method indirectly by calling the non-virtual method call_virtual. If we try to call it directly from inside the destructor GCC 3.3.5 is smart enough to detect it and give out the following error message:

error: abstract virtual `virtual void A::cleanup()' called from
   destructor

or (if it is called from inside the constructor):

error: abstract virtual `virtual void A::cleanup()' called from
   constructor

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: