c++constructorvirtual-functions

Is it ever safe to call a virtual method from a constructor?


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?


Solution

  • 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 {
        }
    };