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?
No, it's just as undefined as calling the virtual function. The instance of B
isn't constructed until after A
s 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>();
}