C++ C++;具有多重继承的协变返回类型错误

C++ C++;具有多重继承的协变返回类型错误,c++,multiple-inheritance,c++98,covariant,C++,Multiple Inheritance,C++98,Covariant,我有一个代码,相当于这个代码: 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>

我有一个代码,相当于这个代码:

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!
};
以及:

我相信我可以在类B或D中编写一些东西来阻止A::foo继承,但我不知道是什么。也许在C++中有一些重命名冲突名称的功能? PS>我不能用C++11,只能用旧的C++98。

你可以用A

通常,返回类型不能是重载的唯一区别。

TL;DR

在类
D
中重写
foo
<由于不相关的
X
Y
返回类型,code>foo方法不能协变。两者都不能因返回类型不同而重载,但签名相同


解释

让我们将代码清理为一个较小的片段,但有相同的问题:

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
中,有一个签名为
X*foo()
的方法继承自
a
,您正在重写方法
Y*foo()
。这些不能协变。另一方面,这个
foo
不能重载另一个

阅读clang的错误消息很好:

错误:虚拟函数“foo”的返回类型与 它重写的函数的返回类型('Y*'不是从'X'派生的 *")


解决方案


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

您是说您不需要在
C
中声明并在
A
中实现的
foo
方法,但是由于您的类
D
也是
A
C
,客户端可能依赖于此方法可用,并返回
X
。C++不支持AFEK移除继承的方法,并且有充分的理由,因为这将违反LISKOV替换原理。


如果您确实在此处删除或隐藏了
C::foo
,则在需要
A
B
C
实例的情况下,无法使用
D
实例。因此,恐怕这里没有解决这个问题的好办法。如果您只想在<代码> >代码> d>代码>中重用“<代码> > <代码> >代码> b>代码,那么在这种情况下,您可能应该考虑构图而不是继承。

如果从<代码> > <代码>继承的<代码> Fo< <代码>是您唯一想要的,那么您为什么继承了<代码> B<代码>?这似乎是一个潜在设计问题的症状。B和D是我在代码中分别使用的两个类。我问了一个类似的问题:,第二个答案可能提供您想要的,但它确实需要c++11。在这个示例中,您认为协方差在哪里使用?协方差意味着重写方法返回被重写方法的返回类型的子类型,这里不是这种情况?你说得对,这里的协方差只是因为错误“无效的协方差返回类型”。谢谢你给出了清晰完整的答案。即使没有D类的继承,您给出的代码(在类中没有实现foo方法)也不会编译。如果我没弄错的话。
error:   overriding 'virtual X* A::foo()'
 X * foo() {};
     ^
class B : private A {};
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>
};
/*virtual*/ Y * foo() {};
virtual Y * foo() {};