C++ Virtual Method return different derived types

Refresh

December 2018

Views

515 time

1

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?

2 answers

0

As written, you will get compiler errors on the .Get() call. If you want to avoid that, make the assignment to base class..

ReturnTypeBase * one = objects[0].Get();
ReturnTypeBase * two = objects[1].Get();

As long as you access 'one' and 'two' through abstract methods defined in the base class, (eg. a 'toString()' method), you won't have problems with the internal data.

If you intend on treating the data the same across all instances of the base class, you might want to considering using a template class instead.

4

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.