将在多重继承中调用哪个实例

Which instance will be called in multiple inheritance?

本文关键字:实例 调用 多重继承      更新时间:2023-10-16

我有两个基类(B1B2),它们是从公共基类(B)派生的,其中它们有一个公共变量(假设:来自B的int x;),在第一个基x=0中,在第二个基x=10中(B1、B2构造函数中给定的默认值)。

现在,如果我再派生一个类(class D : virtual public B1, virtual public B2{})。

根据虚拟概念,这里只有一个x的副本可用,现在如果我尝试使用派生类对象访问x值,我将在O/p(x=0x=10)中获得x的哪个实例,为什么?

提前谢谢。

这不是使用虚拟基类的正确位置(如果您没有进一步派生)。也许你在混淆概念。

class A;
class B : virtual public A
class C : virtual public A
class D : public B, public C

在这种情况下,使基类成为虚拟的是有意义的,因为当你看到D时,有两条通向类A的路径。

您的案例是:-

class B1
{
 public:
    int x;
};
class B2
{
  public :
     int x;
};
class D : public B1, publicB2
{
  public :
     void accessBase ()
     {
       this->x;             //error as ambigous.
       this->B1::x;         //fine it's B1's x.
       this->B2::x;         //fine it's B2's x.
     }
};

根据虚拟概念,这里只有一份x的副本可用

否-virtual基的使用确保了B1B2只有一个副本,但无论如何,继承继承中只列出了一个,因此基的"虚拟性"与此处的功能无关。每个基都是一个不同的类,并且两者仍然具有不同的x成员。因此,您必须使用B1::xB2::x来消除计划使用的歧义,就像碱基不是virtual一样。

考虑:

#include <iostream>
struct B1 { int x; };
struct B2 { int x; };
struct D : virtual B1, virtual B2 { };
int main()
{
    D d;
    d.B1::x = 2;
    d.B2::x = 4;
    std::cout << d.B1::x << ' ' << d.B2::x << 'n';
}

输出:

2 4

这表明它们是自变量。请参阅此处运行的代码

根据虚拟概念,此处只有一份x可用

这是你的问题前提的根本问题,因为这不是真的。

不能仅仅因为将不相关的碱基标记为virtual就"合并"它们。如果B1B2本身都派生自某个VeryBase,那么实际上派生自B1B2意味着您只有一个VeryBase:副本

                 VeryBase
                  /    
                 /      
                B1      B2    (inherited virtually)
                       /
                      /
                     /
                    /
                     D

与相反

          VeryBase      VeryBase
                          /
                         /
                B1      B2    (inherited normally)
                       /
                      /
                     /
                    /
                     D

但你在这里根本不是这么做的。没有VeryBase—只有两个独立的基地:

                B1      B2    (inherited normally or virtually; it doesn't matter)
                       /
                      /
                     /
                    /
                     D

在这种情况下,您的virtual继承根本没有任何区别,因此您仍然有两个int x成员,并且您可以以通常的方式独立访问它们:

void D::foo()
{
   std::cout << B1::x << ' ' B2::x << std::endl;
}