Reputation: 547
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?
Upvotes: 1
Views: 1460
Reputation: 119174
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.
Upvotes: 4
Reputation: 54
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.
Upvotes: 0