当两个顶点虚拟但定期地继承第三个顶点时,虚拟继承三角形如何工作?

Yai*_*air 3 c++ virtual

我有以下代码,我对输出有点困惑:

class A{
    protected:
        int x;
    public:
        A() { x = 1; }
        void print() { cout << "X: " << x << endl; }
};

class B: virtual public A{
    protected:
        int x;
    public:
        B() { x = 2; }
};

class C: virtual public A, public B {
    public:
        C() { x = 3; }
};

int main() { 
    C c;
    c.print();
    return 0;
}

Run Code Online (Sandbox Code Playgroud)

输出为:X 1

有人可以解释一下这是如何发生的过程吗?为什么 C() ctor x = 3 改变 B::x 而不是 A::x?它只有一个父类 A 吗?尽管它定期继承B类

Pet*_*ker 7

这有点棘手。这里的关键术语是统治力。举一个更简单的例子:

struct B: virtual A {
    int x;
};

struct C : B {
    C() { x = 3; }
};
Run Code Online (Sandbox Code Playgroud)

在这里,显然,赋值x = 3;分配给了xin B,因为当编译器看到 inx并且B不查找A另一个时,名称查找就会停止x

在问题的示例中,还有来自的直接继承A

struct C : B, virtual A {
    C() { x = 3; }
};
Run Code Online (Sandbox Code Playgroud)

现在仍然有两个不同的x对象:一个 inB和一个 in A,乍一看,xin的提及C::C()看起来模棱两可:它是来自C's base 的那个B还是来自C's base的那个A

支配规则表示,B该版本是xhidesA版本的版本,尽管它A是 的直接基础C。基本上,规则是,由于A::x沿继承链的一个分支隐藏,因此它沿所有分支隐藏。正式地,

当使用虚拟基类时,可以沿着不经过隐藏声明的子对象晶格路径到达隐藏声明。这并不是含糊之处。

这仅适用于A虚拟基数:

struct C : B, A {
    C() { x = 3; }
};
Run Code Online (Sandbox Code Playgroud)

这里,x是含糊不清的;它可能意味着B::x或者它可能意味着A::x(但不是A::x在虚拟基中B)。