1

I am trying to understand why, and if it is possible to call child method from parent constructor.

First I tried:

#define prn printf(__FUNCTION__);printf("\r\n");

class A
{
public:
    A(){init();}
     ~A(){prn;}

     virtual void f(){}

     virtual void init()=0;
};

class B : public A<B>
{
public:
    B(){prn;}
    ~B(){prn;}

    virtual void init(){prn;}
};

Which crushed with pure virtual call. I can guess its because init() in A() points to init() in A's virtual table. With this line I confirmed it:

virtual void init()=0{prn};

So, I tried the following:

template<typename T>
class A
{
public:
    A(){((T*)this)->init();}
     ~A(){prn;}

     virtual void f(){}

     virtual void init()=0{prn;}
};

class B : public A<B>
{
public:
    B(){prn;}
    ~B(){prn;}

    virtual void init(){prn;}
};

Which also crushed! Now my only guess is that it happens because the virtual table is just being made, but its just a guess...

Can anyone explain what is going on?

Thanks!

TCS
  • 5,790
  • 5
  • 54
  • 86
  • `#define prn printf(__FUNCTION__);printf("\r\n");` at the first line looks **as suspect** as can be! – πάντα ῥεῖ May 04 '14 at 03:49
  • 4
    "The effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined." – Raymond Chen May 04 '14 at 03:52
  • 1
    The base class is constructed before the derived class. The base can't possibly route a virtual call. And a newline is just `\n`. It will get translated into `\r\n` by the compiler if needed. – chris May 04 '14 at 03:53
  • possible duplicate of [C++ constructors: why is this virtual function call not safe?](http://stackoverflow.com/questions/11377629/c-constructors-why-is-this-virtual-function-call-not-safe) – aruisdante May 04 '14 at 04:58

1 Answers1

3

When you are in the base class constructor, the details of the derived class has not been filled in yet -- which means the virtual function table is not completely filled in yet. The virtual function table does not point to any of the derived class functions.

If you call a virtual member function from the base class constructor, several things can happen:

  1. If the base class has an implementation of the function, that will be called. This will be the best case scenario. Remember that it is possible to define a virtual member function in the base class even if it is declared pure virtual.

  2. If the base class does not have a member function, the entry in the virtual function table for the function could be NULL (well initialized) or something uninitialized. You are likely to get an exception thrown or segmentation violation, or any behavior -- you are entering the territory of undefined behavior.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 3
    Well, anything can happen because it's undefined behavior. The vtable is all but guaranteed not to be the one for the derived class, because well-formed virtual dispatches are guaranteed to go to the base class implementation. Most implementations fill pure virtual functions with a stub that terminates the program. Anyway, +1. – Potatoswatter May 04 '14 at 04:01
  • 2
    This is undefined behavior—you're describing what one implementation could do, but it really could do anything. The compiler decides what happens, and it doesn't need to provide a consistent behavior. Very much defined, though: the constructor for the child classes haven't been called yet, so all fields have indeterminate values. – zneak May 04 '14 at 04:06