非钻石继承树中的虚拟继承 - 记忆和行为副作用

时间:2017-02-07 19:57:38

标签: c++ abi virtual-inheritance memory-layout

我理解钻石继承树中虚拟继承效果,但不理解非钻石继承树中的副作用(如果有)。

如果你有

class A;

class B: public virtual A;

这两个类的行为内存布局(如果有),即构造函数调用的顺序等有什么不同。

假设class A有数据成员。

请提供您的答案的官方文档

2 个答案:

答案 0 :(得分:2)

虚拟继承的一个影响是static_cast的向下转换不起作用。如果您想从虚拟基础向下转发,则必须改为使用dynamic_cast

A* pa = new B;
B* pb1 = static_cast<B*>(pa); // doesn't work: compilation error
B* pb2 = dynamic_cast<B*>(pa); // works

引自标准(5.2.9):

  

类型为“指向cv1 B的指针”的prvalue,其中B是类类型,可以转换为类型为“指向cv2 D的指针”的prvalue ...如果... B   既不是D的虚基类,也不是D的虚基类的基类。

答案 1 :(得分:0)

关于内存布局,一些编译器可能会将虚拟基础数据成员放在子类的数据成员之后(参见Multiple Inheritance Considered Useful):

class A {
public:
    int a;
};

class B : public virtual A {
public:
    int b;
};

int main() {
    B b;

    std::cout << "&b.a < &b.b = " << (&(b.a) < &(b.b)) << std::endl; // &b.a < &b.b =  = 0

    return 0;
}

另一方面,非虚拟基地的数据成员通常在之前在孩子的数据成员之前放置:

class A {
public:
    int a;
};

class B : public virtual A {
public:
    int b;
};

int main() {
    B b;

    std::cout << "&b.a < &b.b = " << (&(b.a) < &(b.b)) << std::endl; // &b.a < &b.b = 1

    return 0;
}