I am aware that it is unsafe to call a virtual method from within the constructor of the class in which the method is declared virtual (or pure virtual).
However, I am wondering if the following is safe:
class Base
{
public:
void helper()
{
this->foo();
}
protected:
virtual void foo() = 0;
};
class Derived : public Base
{
public:
Derived()
{
this->helper();
}
protected:
void foo() override
{
//...
}
};
Yes, the virtual method foo()
is called from within a constructor, but it is called from within the constructor for the class which implements foo()
.
Here is a working example: https://godbolt.org/z/nz4YsbqYT
But, is this well-defined by the standard for all compilers?
I am wondering if the following is safe:
Yes, in the example you've given, it is.
... is this well-defined for all compilers by the standard?
Yes. *this
is a Derived
in the constructor of Derived
, so Derived::foo
will be called from helper
.
Safe? Well... If you expect everyone to know how it works, it is. Someone may however do:
class EvenMoreDerived : public Derived {
protected:
void foo() override {
std::cout << "not called\n";
}
};
... and, without other additions, expect this version of foo
to be called when instantiating an EvenMoreDerived
. That will of course not happen since the call to helper
is done in the Derived
constructor, so it'll still be Derived::foo
that's being called, not EvenMoreDerived::foo
.
One possible way to avoid mistakes like that if you want to call virtual
methods in the constructor is to make the class final
:
class Derived final : public Base { // the above mistake will not be so easy to make
};
... or make foo
final
:
class Derived : public Base {
protected:
void foo() override final {
}
};