【问题标题】:How do I use the override keyword for multiple generic inheritance in C++?如何在 C++ 中使用 override 关键字进行多泛型继承?
【发布时间】:2014-12-01 12:37:49
【问题描述】:

我有一个通用的 IDetachable 接口,它提供了一种方法:

template<class T>
class IDetachable {
public:
  virtual T detached() const = 0;
};

我有这些示例类:

class A: public IDetachable<A> {
  virtual A detached() const override {
    // some implementation which returns a detached A object
  }
};

继承B时出现问题:

class B: public A, public IDetachable<B> {
  virtual B detached() const override {
    // some implementation which returns a detached B object
  }
};

clang++ 告诉我:

error: virtual function 'detached' has a different return type ('B')
  than the function it overrides (which has return type 'A')

在我看来,编译器自动为 override 关键字选择了第一个父级。有没有机会告诉编译器我打算用 override 关键字继承哪个父方法?

【问题讨论】:

  • 这就是override的重点——如果派生类中的函数签名与基类中的函数签名不完全相同,则会导致错误。
  • @JonathanPotter 我相信关键是他希望它覆盖IDetachable&lt;B&gt; 中的detached 而不是A
  • 第一个基类无论如何都不是特殊的。虚函数必须正确地覆盖所有父函数。如果那不可能,您根本无法覆盖。
  • @JonathanPotter:签名确实与基类之一匹配。问题是它试图覆盖两个冲突的函数,不管有没有override,这是一个错误。
  • 正如@AdrianMay 回答的那样,您不能在它们的返回值上唯一地重载两个具有相同名称的不同函数;它们的参数列表也必须不同。需要明确的是,您不能同时拥有A detachable()B detachable(),因为这两者之间的唯一区别是它们的返回值;但是,您可以使用 A detachable(A*)B detachable(B*)

标签: c++ generics inheritance


【解决方案1】:

您只想要返回类型协方差吗?它仅适用于指针和引用:

template<class T>
class IDetachable {
public:
    virtual T* detached() const = 0;
};


class A: public IDetachable<A> {
    virtual A* detached() const override {
        // some implementation which returns a detached A object
    }
};

class B: public A, public IDetachable<B> {
    virtual B* detached() const override {
        // some implementation which returns a detached B object
    }
};

int main() {
    IDetachable<A> *da = new A;
    A *a = da->detached();
    IDetachable<B> *db = new B;
    B *b = db->detached();
}

【讨论】:

【解决方案2】:

你可以传递一个虚拟的 T 来分离:

template<class T>
class IDetachable {
public:
  virtual T detached(T*dummy) const = 0;
};

您忽略该参数,但现在您可以专注于它。

【讨论】:

  • 如果不带参数调用函数调用是不明确的(由于默认参数值)。
  • 所以,为了避免错误,我建议去掉默认参数,无论如何你都需要一个参数来消除函数的歧义,不是吗?
  • @AdrianMay 您可以使用 detach((A*)null) 调用它,或者 - 我将在我的代码中使用 - 你将它作为 IDetachable& 传递给调用该方法的方法.
【解决方案3】:

问题不在于如何覆盖其中一个,而是您不能拥有两个具有相同签名和不同返回类型的函数。

考虑:

template<class T, class U>
class IDetachable {
public:
    virtual ~IDetachable() {}
    virtual T detached() const = 0;
    virtual U detached() const = 0; // whoopse problem
};

不管你如何最终得到两个相同签名的函数返回不同的类型,它总是非法的。

@AdrianMay 提供了一个可行的答案。他更改了函数的签名。

【讨论】:

  • 你可以从不同的基础继承这些函数。
  • @n.m.我不太确定怎么做?如果我将具有不同返回类型的相同函数放在不同的基类中并从每个基类中继承,我仍然会得到相同的错误。还是我错过了什么?
  • @n.m.你的例子甚至和OP一样吗?你没有使用模板,也没有使用纯虚函数!
  • @PaperBirdMaster 模板与问题正交。如果其中一个冲突函数是纯虚函数,则永远无法实例化您的类,因为您无法覆盖。
  • @Galik 这是对问题的一个很好的解释。我猜 Adrian May 的解决方案是相当有用的。
猜你喜欢
  • 1970-01-01
  • 2015-05-12
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多