如何在C++中使用override关键字实现多个泛型继承?

9

我有一个通用的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的作用 - 如果派生类中函数的签名与基类中的函数不完全相同,它将导致错误。 - Jonathan Potter
@JonathanPotter 我认为重点在于他希望它覆盖 IDetachable<B> 中的 detached 而不是 A - T.C.
2
第一个基类在任何方面都不是特殊的。虚函数必须正确地覆盖所有父类。如果不可能,那么你就无法进行覆盖。 - n. m.
3
签名确实与其中一个基类的签名匹配。问题在于它试图覆盖两个冲突的函数,这是使用或不使用 "override" 都会出错的问题。 - Mike Seymour
你的意图是让类 B 拥有两个 detached() 函数——一个返回 A,另一个返回 B——还是只有一个这样的函数? - seh
显示剩余3条评论
3个回答

6
问题不在于如何覆盖其中一个,而在于不能有两个具有相同签名但返回类型不同的函数。
考虑以下情况:
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. 我不太确定怎样做?如果我将具有不同返回类型的相同函数放置在不同的基类中,并从每个基类继承,我仍然会得到相同的错误。或者我有什么遗漏吗? - Galik
@n.m.,你的示例是否与原帖相同?你既没有使用模板,也没有使用纯虚函数! - PaperBirdMaster
@PaperBirdMaster 模板与此问题无关。如果其中一个冲突函数是纯虚函数,那么您的类将无法实例化,因为您无法进行覆盖。 - n. m.
@Galik 这是一个很好的问题解释。我想Adrian May的解决方案非常实用。 - Polem

3
你可以将一个虚拟 T 参数传递给detach函数:
template<class T>
class IDetachable {
public:
  virtual T detached(T*dummy) const = 0;
};

你忽略了那个参数,但现在你可以专门针对它进行优化。


如果没有传递参数调用函数(由于默认参数值),则函数调用是不明确的。 - PaperBirdMaster
所以,为了避免错误,我建议去掉默认参数,你总需要一个参数来消除函数的歧义,不是吗? - PaperBirdMaster
@AdrianMay 你可以使用detach((A*)null)来调用它,或者 - 在我的代码中我会使用的方式 - 将其作为IDetachable<A>&传递到一个调用该方法的方法中。 - Polem

2

你是想要返回类型协变吗?它只适用于指针和引用:

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

可运行的示例代码在此处。(这样您就可以看到对于每个IDetachable指针调用detached函数会产生您想要的效果。) - idbrii

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接