【问题标题】:How does virtual inheritance actually work?虚拟继承实际上是如何工作的?
【发布时间】:2023-03-23 07:01:02
【问题描述】:

我知道钻石问题,但问题是 - 当我在谷歌上搜索“虚拟继承”时,结果提到了钻石问题。我想知道它一般是如何工作的,以及它与普通继承有何不同。

我知道当一个类(通常)从另一个类继承时,它只包含它的所有成员(字段和方法,撇开访问级别)。其中一些可能会被新成员覆盖或隐藏,但它们仍然存在。继承还定义了层次结构中的类之间的某些关系,这会影响强制转换和多态性。

现在虚拟继承有何不同?例如:

class A
{
    public:
    int a;
    int b;
    void fun(int x)
    {}
    void gun(int x)
    {}
};

class B : public A
{
    public:
    int a;
    int c;
    void fun(int x)
    {}
    void hun(int x)
    {}
};

class C : virtual public A
{
    public:
    int a;
    int c;
    void fun(int x)
    {}
    void hun(int x)
    {}
};

BC 有什么区别?我的示例没有利用其他差异吗?标准是怎么说的?另外,如果 C++03 和 C++11 有区别,请指出。

【问题讨论】:

  • 区别在于继承自B的类和继承自C的类。
  • 你只能得到关于可怕的死亡钻石的结果的原因是因为这是虚拟继承解决的唯一问题。区别在于 DDoD 中派生度最高的类。
  • 你是说只有 1 级继承(Base - Derived),除了实现细节(如vtable)之外,普通继承和虚拟继承之间绝对没有任何区别 ?

标签: c++ inheritance virtual-inheritance


【解决方案1】:

对于单级继承,行为没有区别。

不同之处在于从多个基类继承时,这些基类本身有一个共同的基类:

struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : B,C {};

在这个例子中,使用虚拟继承,D 只包含一个A 子对象,它的BC 子对象共享;这是“钻石”图案:

    A
   / \
   B C
   \ /
    D

如果没有虚拟继承,它将包含两个A 子对象,并且没有“钻石”:

   A A
   | |
   B C
   \ /
    D

无论有没有多重继承,如果您有多个继承级别,仍然存在差异:虚拟基类必须由最派生的类初始化,而不是由其直接派生类初始化。这是为了避免多重继承情况下的歧义,其中(在上面的示例中)BC 将负责初始化共享的 A

【讨论】:

  • 所以换个说法:虚拟继承唯一要做的就是确保任何派生对象(在层次结构中的任何级别)都包含虚拟继承类的一个子对象?
猜你喜欢
  • 2017-07-05
  • 2012-08-31
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
  • 2016-10-26
  • 1970-01-01
  • 2013-08-24
相关资源
最近更新 更多