Inheritance, Constructors, Virtual Methods and typeid

Posted by Kaya Kupferschmidt • Wednesday, May 3. 2006 • Category: C++
When working with inheritance and virtual methods, there might be some surprises when one tries to call a virtual method inside a constructor - and this is the reasons why one should never ever call virtual methods inside a constructor or inside a destructor.

Consider the following simple code
class A {
public:
    A() {
        printf("A::A() calls ");
        f();
    }
    ~A() {
        printf("A::~A() calls ");
        f();
    }
    virtual void f() {
        printf("A::f()\n");
    }
};


class B : public A {
public:
 	B() {
     		printf("B::B() calls ");
     		f();
 	};
 	~B() {
     		printf("B::~B() calls ");
     		f();
 	};
 	virtual void f() {
     		printf("B::f()\n");
 	};
};	


void main(void) {
 	B obj;
 	obj.f();
};


Guess what the output will look like. Some people might expect something like follows:
A::A() calls B::f()
B::B() calls B::f()
B::~B() calls B::f()
A::~A() calls B::f()

But unfortunately this turns out to be wrong. You will actually see the following output
A::A() calls A::f()
B::B() calls B::f()
B::~B() calls B::f()
A::~A() calls A::f()

This behaviout actually is orrect and makes a lot of sense. Remember that when the constructor A::A() is called, the object actually is still of type A and not of type B yet. The same is true with destructors. When A::~A() is called, the destructor of the derived class B::~B() has already been called, thus the object isn't of type B any more. You can verify this claim by printing the typeids of the classes inside the constructor and dstructor, like follows:
class A {
public:
    A() {
        printf("A::A() is of type %s\n",
            typeid(*this).name());
    }
    ~A() {
        printf("A::~A() is of type %s\n",
            typeid(*this).name());
    }
    virtual void f() {
    }
};


class B : public A {
public:
    B() {
        printf("B::B() is of type %s\n",
            typeid(*this).name());
    }
    ~B() {
        printf("B::~B() is of type %s\n",
            typeid(*this).name());
    }
    virtual void f() {
    }
};	

void main(void) {
    B obj;
};

This example will produce the following output:
A::A() is of type class A
B::B() is of type class B
B::~B() is of type class B
A::~A() is of type class A

Thus it is impossible to detect the real class type inside a constructor or detructor.

0 Comments

Display comments as (Linear | Threaded)
  1. No comments

Add Comment


Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Markdown format allowed



A Simple Sidebar