C++ 在C+中查找内存中某类对象布局的算法+;

C++ 在C+中查找内存中某类对象布局的算法+;,c++,inheritance,multiple-inheritance,C++,Inheritance,Multiple Inheritance,考虑以下代码: class A { public:     virtual ~A();     virtual void foo(); }; class B : public A { public:     virtual ~B();     virtual void foo(); }; 内存中B类对象的布局如下所示: 当我们谈到多重继承时,在内存中布局某个类的对象变得很困难,特别是当我们谈到菱形继承时,或者当我们谈到虚拟类时,如: class E : public C, public vi

考虑以下代码:

class A {
public:
    virtual ~A();
    virtual void foo();
};
class B : public A {
public:
    virtual ~B();
    virtual void foo();
};
内存中B类对象的布局如下所示:

当我们谈到多重继承时,在内存中布局某个类的对象变得很困难,特别是当我们谈到菱形继承时,或者当我们谈到虚拟类时,如:

class E : public C, public virtual D, public virtual B {
public :
    E() {
        cout << "E::E()" << endl;
    }
    E(int x) : D(x) {
        cout << "E::E(int)" << endl;
    }
};
E类:公共C、公共虚拟D、公共虚拟B{
公众:
E(){

cout布局取决于编译器所针对的ABI。您应该研究ABI的文档,以了解类在内存中的布局方式


例如,使用.

< P>我假定你所给的图表认为C++是带有额外的C,并且从那个角度对实现定义的行为做出了假设。 它从左到右读取基说明符列表,深度优先,并假设虚拟继承是单个指针。每个带标签的框对应于类的非静态数据成员子对象(其中没有)。未标记的框是指向虚拟基的指针

我们从
E
开始。它有一个非虚拟
C
库,一个虚拟
B
库和一个虚拟
D
库。
C
有一个虚拟的
B
子对象,它成为指针。 虚拟
B
已经有一个指针,它将指向与
C
的底部相同的位置。 虚拟
D
需要一个指针

这结束了
E
的非虚拟基,但仍有一些虚拟基尚未存储

我们制作了a
B
,其中有一个非虚拟的
a
,并在
E
中记录偏移量。
我们制作了一个
D
,它有一个非虚拟的
B
,它有一个非虚拟的
a
,并在
E
中记录偏移量,除了标准布局类型外,它是实现定义的,可能也未指定:

对于多重继承模式,您可以使用static_cast来收集它的布局方式——尽管当时还没有gaurentee:如下所示:

void* offsetToB = static_cast<B*>(static_cast<A*>(nullptr));
void*offsetToB=static_cast(static_cast(nullptr));

免责声明:这不安全。

没有固定或“标准”布局。它取决于ABI和编译器。请注意,虚拟表已经是一个实现细节。它是一个突出的细节,因为(几乎?)每一个实现都使用它,尽管C++标准不关心虚拟表,也没有什么可以依赖于该图看起来误导我。这些空白意味着<代码> E<代码>对象不连续地注意到,没有任何可移植的知识,你可以用这样一个怪物的布局来做。听起来像YO。有一位老师,你正在教C++misconceptions@vesii不会改变任何关于答案的东西。每个ABI都有自己的C++类布局规则(=算法)。