c++inheritanceconstructorundefined-behaviorvirtual-functions

Is it allowed to pass "this" of derived class to constructor of base class?


Here is the code I originally wanted to write:

class A {
public:
    A(someType someData) {
        this->init(someData);
    }
   
    virtual void init(someType) = 0;
}

This is not allowed, because at the point when base class constructor is called, instance of the derived class doesn't exist yet. So I changed it to this:

class A {
public:
    A(someType someData, A* derived) {
        derived->init(someData);
    }
   
    virtual void init(someType) = 0;
}

class B : public A {
public:
    B(someType someData)
    : A(someData, this) {}
    
}

The code compiles and runs without crashing but is it allowed or UB?


Solution

  • No, it's just as undefined as calling the virtual function. The instance of B isn't constructed until after As constructor completes so you can't call virtual functions on it.

    One approach to fix this is to do a two stage construction, fully construct the class, and only then, call the virtual method:

    class A {
    public:
        virtual void init(someType) = 0;
    
        template <typename T>
        static T construct(someType someData)
        {
           T obj;
           obj.init(someData);
           return obj;
        }
    }
    
    class B : public A {
    public:
        void init(someType) override
        {}
    }
    
    int main()
    {
      B b = A::construct<B>();
    }