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() {};
^
我相信我可以在B类或D以防止A :: foo从继承,但我不知道是什么。也许有一些功能可以重命名C++中的冲突名称?
PS>我不能使用C++ 11,只能使用旧的C++ 98。
TL; DR在D
类
foo
重写。 foo
方法由于不相关的X
和Y
返回类型而不能协变。也不能由于不同的返回类型而签名相同而不能重载。
说明
让我们清理代码用同样的问题较小的片段:
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
继承A
和C<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() {};
解决方案
最好的解决方法是简化您的设计,摆脱这些复杂的继承,模板和相同的名称方法!
感谢您提供清晰和完整的答案。即使没有_D_类的继承,您正在给出的代码(不在_A_类中实现_foo_方法)也不会编译。如果我理解你是对的。 – 2015-02-25 13:32:52
你测试了吗?它不适合我。 – deepmax 2015-02-24 13:32:19
对我来说也是。 http://ideone.com/uv7MKB – 2015-02-24 13:35:43
你说你不需要foo
方法,你在C<X>
声明和A
实现,但因为你的D
类也是安A
和C<X>
,客户端可能会依赖于这种方法可用,并返回一个X
。 C++不支持删除继承的方法AFAIK,并有充分的理由,因为这会违反Liskov替换原则。
如果你没有删除或隐藏C<X>::foo
这里,那么不能使用的D
一个实例,其中的A
,B
,或C<X>
实例的预期。所以恐怕这里没有解决这个问题的好办法。如果您只是试图重复使用D
中的A
或B
实现,那么在这种情况下您应该考虑组合而不是继承。
如果从'C'继承的'foo'是你想要的唯一一个,那你为什么要从'B'继承?这似乎是一个潜在设计问题的症状。 –
2015-02-24 13:45:37
B和D是我在代码中分别使用的两个类。 – 2015-02-24 14:17:02
我已经问过一个类似于这个问题: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