Search code examples
c++multiple-inheritancec++98covariant

C++ covariant return type error with multiple inheritance


I have the code which is equivalent to this one:

class X {};
class Y {};

template< typename T>
  class C {
  public:
      virtual  T * foo() = 0;
  };

class A : public C< X> {
public:
    X * foo() {};
};

class B : public A {};

class D : public B, public C< Y> {
public:
    Y * foo() {}; //this is the only one method I need here. Not A::foo!
};

I got this errors:

error:   invalid covariant return type for 'virtual Y* D::foo()'
 Y * foo() {};
     ^

and:

error:   overriding 'virtual X* A::foo()'
 X * foo() {};
     ^

http://ideone.com/PAgTdX

I believe I could write something in class B or D to prevent A::foo from inheriting, but I don't know what. Maybe there is some feature to rename conflict names in C++?

PS> I can't use C++11, only good old C++98.


Solution

  • TL;DR

    Overriding foo in class D. foo methods can not covariant due to unrelated X and Y return types. Neither, can not overload due to different return types but same signature.


    Explanation

    Let's clean up the code to a smaller snippet with same issue:

    class X {};
    class Y {};
    
    template<typename T>
    class C {
    public:
        virtual T * foo() = 0;
    };
    
    class A : public C<X> {
    public:
        // Your code:
        // X * foo() {}; <---- This method is irrelevant to the problem
    
        // virtual X * foo() {};
        // ^^^^^^^^^^^^^^^^^^^^^
        // This method declared via inheritance and template
        // and implicitly exists in this class, (look at keyword `virtual`)
    };
    
    class D : public A, public C<Y> {
    public:
        /*virtual*/ Y * foo() {}; // `virtual` comes from C<X>
    };
    

    Well, class D inherits two foo methods from A and C<Y>. These two imported methods can co-exists because they come from different parents and they can be called by qualified calls, for example D d; d.A::foo();.

     

    But in this situation, the problem comes into the picture, when you try to override foo in class D:

    /*virtual*/ Y * foo() {};
    

    In class D, there is a method with signature X * foo() inherited from A and you're overriding method Y * foo(). These can not covariant, because Y is not derived from X. On the other hand, this foo can not overload another one, Because return type is not part of function signature.

     

    It's good to read the error message of clang:

    error: return type of virtual function 'foo' is not covariant with the return type of the function it overrides ('Y *' is not derived from 'X *')

    virtual Y * foo() {};
    

    Solution

    The best solution is to simplify your design and get rid of these complex inheritance, templated and same name methods!!