c++pointerscovariant-return-types

C++ : Covariant return type without pointer


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 ?


Solution

  • 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.