I create two simple classes by inheritance, and I add a virtual function and the override in the child class.
class Parent
{
public:
virtual Parent foo();
};
class Child : public Parent
{
public:
Child foo() override;
};
In this case, my overridden function get an error : error C2555: 'Child::foo': overriding virtual function return type differs and is not covariant from 'Parent::foo'
If I change return types with pointer :
class Parent
{
public:
virtual Parent* foo();
};
class Child : public Parent
{
public:
Child* foo() override;
};
the error gone ! I don't understand why the covariance of return types must be done with pointer and I can't use value type or a reference. Some website or forums explain that because the returned value is a copy of the value used in the function, the compiler know the constant size of a pointer, but must indicate different size for the overridden function and the parent function, which is apparently impossible.
So, why can't I use anything else than pointer in this case ? If I want the child type in the overridden function without using pointers, must I return the base class for each functions and cast the returned type into the child type ?
The idea of a covariant return type is a polymorpihc return type. And in C++, you can't have run time polymorphism without pointers or references. Let's ignore for a second most of the hardships, and pretend it's possible. Here is my code that handles things by your Parent
interface:
void bar(Parent * p) {
auto o = p->foo();
}
What is o
? Well, it's Parent
of course. Says so in Parent::foo
's return type. But what if that p
is pointing at a Child
? The deduced type of o
is still Parent
, so at best I get a sliced object. No polymorphic behavior, so the whole exercise is pointless.
At worst, and quite likely, I get undefined behavior.
That's why co-variant return types have to be pointers or references.