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

时间:2014-11-12 11:35:33

标签: c++ multiple-inheritance virtual-inheritance

我有2个基类(B1B2),它们来自公共基类(B),它们有一个公共变量(let:int x;来自基数B) ,在第一个基地x=0,在第二个基地x=10(B1,B2构造函数中给出的默认值)。

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

此处只有一个x副本可用于虚拟概念,现在如果我尝试使用派生类对象访问x值,我将进入x的实例/ p(x=0x=10),为什么?

提前致谢。

3 个答案:

答案 0 :(得分:4)

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

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.
     }
};

答案 1 :(得分:2)

  

这里只有一个x副本可用于虚拟概念

不 - 使用virtual个基数可以确保只有B1B2之一的副本,但只有一个列在无论如何继承heirarchy所以"虚拟"基数与此处的功能无关。每个基类都是一个独特的类,两者都有不同的x成员。因此,您必须使用virtualB1::x消除您计划使用的内容,就像基数不是B2::x一样。

考虑:

#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

这表明他们是自变量。请参阅运行here

的代码

答案 2 :(得分:1)

  

根据虚拟概念,此处只有x的一份副本

这是问题前提的根本问题,因为不正确

不相关的基础不能仅仅因为您标记virtual而“合并”。如果B1B2本身都来自某些VeryBase,那么虚拟派生自B1B2意味着您只有一份{{1} }}:

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