c++c++11virtual-functionscovariant-return-types

C++ invalid conversion error using covariant return types with virtual functions


In the following code, I can assign the return of the D::clone() to a pointer to B, but not a pointer to D. Is is possible to return the actual polymorphic type from a call of the base pointer?

struct B
{
    virtual B * clone() { return this; }
};

struct D : B
{
    D * clone()
    {
        std::cout << std::is_same<decltype(this), D *>::value << std::endl;
        return this;
    }
};

int main()
{
    B * b = new D();
    B * bb = b->clone(); // prints "1"
    std::cout << std::is_same<decltype(b->clone()), D *>::value << std::endl; // prints "0"
    D * d = b->clone(); // error: invalid conversion from B * to D * (GCC 5.1)
}

Solution

  • No. A call of clone() on the base B class of a D will return the D* cast to a B*.

    You can reverse this by doing a static_cast<D*> if you are absolutely certain, or a dynamic_cast<D*> if you are not certain. If you are certain, than you should really make the variable b be a D*.

    In C++, you should encode what you know about the state of the program at compile time regardless of the run time situation as types. By storing the D* into B* b, you are telling the compiler not to "know" that the data being pointed to "is a D". Instead, you are saying "the code using B*b should be valid for any pointer-to-B. Clearly D* d = b->clone(); is not guaranteed to be valid for every pointer-to-B.