C++多重继承协变返回类型错误

问题描述:

我有这相当于代码这一个:C++多重继承协变返回类型错误

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! 
}; 

我得到这个错误:

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

和:

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

http://ideone.com/PAgTdX

我相信我可以在B类D以防止A :: foo从继承,但我不知道是什么。也许有一些功能可以重命名C++中的冲突名称?

PS>我不能使用C++ 11,只能使用旧的C++ 98。

+0

如果从'C '继承的'foo'是你想要的唯一一个,那你为什么要从'B'继承?这似乎是一个潜在设计问题的症状。 – 2015-02-24 13:45:37

+0

B和D是我在代码中分别使用的两个类。 – 2015-02-24 14:17:02

+0

我已经问过一个类似于这个问题:http://*.com/questions/28240936/whats-the-best-way-to-implement-ast-using-visitor-pattern-with-return-value,the第二个答案可能会提供你想要的,但它确实需要C++ 11。 – swang 2015-02-24 14:29:29

TL; DRD

foo重写。 foo方法由于不相关的XY返回类型而不能协变。也不能由于不同的返回类型而签名相同而不能重载。


说明

让我们清理代码用同样的问题较小的片段:

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> 
}; 

嗯,类D继承AC<Y> 2种foo方法。这两种导入的方法可以共存,因为它们来自不同的父母,可以通过合格的呼叫来呼叫,例如D d; d.A::foo();

 

但在这种情况下,问题就来了进入画面,当您尝试D类重写foo

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

D类中,有一个与遗传签名X * foo()的方法从A开始,并且您正在重写方法Y * foo()。这些不能协变,because Y is not derived from X。另一方面,foo不能超载另一个,Because return type is not part of function signature

 

这是很好的阅读铛的错误消息:

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() {}; 

解决方案

最好的解决方法是简化您的设计,摆脱这些复杂的继承,模板和相同的名称方法!

+0

感谢您提供清晰和完整的答案。即使没有_D_类的继承,您正在给出的代码(不在_A_类中实现_foo_方法)也不会编译。如果我理解你是对的。 – 2015-02-25 13:32:52

你可以使用private inheritance为A.

class B : private A {}; 

一般情况下,返回类型不能超载的唯一区别。

+1

你测试了吗?它不适合我。 – deepmax 2015-02-24 13:32:19

+0

对我来说也是。 http://ideone.com/uv7MKB – 2015-02-24 13:35:43

你说你不需要foo方法,你在C<X>声明和A实现,但因为你的D类也是安AC<X>,客户端可能会依赖于这种方法可用,并返回一个X。 C++不支持删除继承的方法AFAIK,并有充分的理由,因为这会违反Liskov替换原则。

如果你没有删除或隐藏C<X>::foo这里,那么不能使用的D一个实例,其中的AB,或C<X>实例的预期。所以恐怕这里没有解决这个问题的好办法。如果您只是试图重复使用D中的AB实现,那么在这种情况下您应该考虑组合而不是继承。