c++return-typevirtual-functionsstatic-typingcovariant-return-types

C++ Virtual Method return different derived types


Referencing this question: C++ virtual function return type

Let's consider the following set of objects.

class ReturnTypeBase
{
};

class ReturnTypeDerived1 : public ReturnTypeBase
{
public:
    int x;
};

class ReturnTypeDerived2 : public ReturnTypeBase
{
public:
    float y;
};

class Base
{
public:
    virtual ReturnTypeBase* Get() = 0;
};

class Derived1: public Base
{
public:
    virtual ReturnTypeDerived1* Get()
    {
        return new ReturnTypeDerived1();
    }
};

class Derived2: public Base
{
public:
    virtual ReturnTypeDerived2* Get()
    {
        return new ReturnTypeDerived2();
    }
};

Can these objects be used in the following way?

Base* objects[2];

objects[0] = new Derived1();

objects[1] = new Derived2();

ReturnTypeDerived1* one = objects[0]->Get();

ReturnTypeDerived2* two = objects[1]->Get();

I'm assuming since the return types are covariant(?), that the set of objects above is legal C++. Will the appropriate Get() method be called? Can the pointers one/two be assigned the return value of the Get() method without casting?


Solution

  • The code will not compile as written. Because objects[0] has static type Base*, invoking the Get function results in a pointer with static type ReturnTypeBase* being returned. Since this is an overridden virtual function, the derived class's Get function will be called as you would expect, and the returned pointer would actually point to a ReturnTypeDerived1 object, but the compiler can't prove this. You would need a cast:

    auto one = static_cast<ReturnTypeDerived1*>(objects[0]->Get());
    auto two = static_cast<ReturnTypeDerived2*>(objects[1]->Get());
    

    If you make ReturnTypeBase a polymorphic type, you can use dynamic_cast here instead to avoid undefined behaviour if you happen to be wrong about the dynamic type.