【问题标题】:C++ Virtual Inheritance of virtual method虚拟方法的C++虚拟继承
【发布时间】:2015-09-09 11:54:39
【问题描述】:
struct A {
    virtual void foo() { std::cout << "a";};
};

struct B:public virtual A {
    void foo() { std::cout << "b";}
};

struct C:public virtual A {
    void foo() { std::cout << "c";}
};

struct D:public B, public C {

};
int main() {
    return 0;
}

所以这个在编译时给了我们以下错误:

 \main.cpp:16:8: error: no unique final overrider for 'virtual void A::foo()' in 'D'
 struct D:public B, public C {

如果我们让 B 和 C 结构的继承成为非虚拟的,那么代码正在编译没有任何错误(当然,如果我们调用 dd.foo( ))。那么有什么区别呢?为什么虚拟继承类会报错,直接继承不会报错?

【问题讨论】:

  • 我认为这不是stackoverflow.com/questions/21558/…的复制品
  • 我投票支持重新开放。这个问题是关于一个特定的细节,在标记的副本中没有详细介绍。
  • @OthmanBenchekroun,答案不是直接在虚拟继承的定义中,而是从定义中得出。
  • @chris 我同意,它仍然需要解释(就像你做的那样)
  • 错误的哪一部分不清楚?没有唯一的最终覆盖器。

标签: c++ inheritance virtual virtual-inheritance


【解决方案1】:

A 设为BC虚拟 基类可确保D 恰好包含一个A 子对象[1]。为此,BC 都为foo[2] 提供了最终覆盖,并且两者都被D[2] 继承,所以@987654330 @ 有两个用于 foo 的最终覆盖器,导致程序格式错误[2]

A不是BC 的虚拟基类时,D 将包含两个不同的A 子对象[1] .这些子对象中的每一个都有自己继承的 foo[2] 的最终覆盖器。


[1]:N4140 §10.1 [class.mi]/4:

不包含关键字 virtual 的基类说明符指定非虚拟基类。包含关键字 virtual 的基类说明符指定虚拟基类。对于每个不同的事件 对于最派生类的类格中的非虚拟基类,最派生对象应包含该类型的相应不同基类子对象。对于每个指定为虚拟的不同基类,最派生对象应包含该类型的单个基类子对象。

[2]:§10.3 [class.virtual]/2(强调我的):

如果虚成员函数 vf 在类 Base 和 Derived 类中声明,直接或间接从 Base 派生,则具有相同名称、参数类型列表、cv 限定和引用的成员函数 vf限定符(或不存在)作为 Base::vf 被声明,然后 Derived::vf 也是虚拟的(无论它是否如此声明)并且它覆盖 Base::vf。 为方便起见,我们说任何虚函数都会覆盖自己。 类对象 S 的虚拟成员函数 C::vf 是最终覆盖器,除非以 S 为基类子对象(如果有)的最派生类声明或继承了另一个覆盖 vf 的成员函数。在派生类中,如果基类子对象的虚成员函数具有多个最终覆盖器,则程序格式错误。

【讨论】:

  • 我也有同样的想法,所以这个看起来不错,谢谢 :) 所以当我们有菱形继承时,我们不知道哪个 foo 覆盖了 A 子对象
  • @Utikeev,由于BC 都覆盖它,D 必须提供自己的,这将成为唯一的最终覆盖器(并将导致 B 和 @ 987654342@ 失去其最终覆盖者状态)。
  • @chris 上面 [class.virtual]/2 中提到的实体S 到底是什么?
  • @Alexander,它看起来是该类的任意对象,因此您可以将其替换为您应用它的任何具体对象。
猜你喜欢
  • 1970-01-01
  • 2016-03-26
  • 2011-01-08
  • 1970-01-01
  • 2016-10-26
  • 2016-03-04
相关资源
最近更新 更多