4

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.

4

3 回答 3

2

TL;博士

foo在课堂上压倒一切D。由于不相关和返回类型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继承了两个foo方法。这两个导入的方法可以共存,因为它们来自不同的父级,并且可以通过合格的调用来调用,例如.AC<Y>D d; d.A::foo();

 

但是在这种情况下,当您尝试foo在类中覆盖时,问题就出现了D

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

在类D中,有一个签名X * foo()继承自的方法A,您正在覆盖方法Y * foo()。这些不能协变,因为Y不是从X. 另一方面,这foo不能重载另一个,因为返回类型不是函数签名的一部分

 

看看clang的错误信息就好了:

错误:虚函数“foo”的返回类型与其覆盖的函数的返回类型不协变(“Y *”不是从“X *”派生的)

virtual Y * foo() {};

解决方案

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

于 2015-02-24T13:41:41.547 回答
0

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

如果您确实C<X>::foo在此处删除或隐藏,则D无法在需要 、 或 的实例的地方使用AB实例C<X>。所以我担心这个问题在这里没有很好的解决方案。如果您只是想重用 fromABin 的实现D,那么在这种情况下您可能应该考虑组合而不是继承。

于 2015-02-24T14:49:50.870 回答
-1

您可以对 A使用私有继承。

class B : private A {};

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

于 2015-02-24T13:28:38.553 回答