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

时间:2019-07-02 10:06:47

标签: c++ inheritance multiple-inheritance

考虑以下代码:

class A {
public:
    virtual ~A();
    virtual void foo();
};
class B : public A {
public:
    virtual ~B();
    virtual void foo();
};

B类对象在内存中的布局如下:

enter image description here

当我们谈论多重继承时,尤其是当我们谈论菱形继承,或者当我们谈论诸如以下的虚拟类时,很难在内存中布置某个类的对象:

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

我正在寻找一些伪算法,该伪算法说明如何显示此布局。有没有我可以遵循并手动构建这些布局(没有虚拟表)的算法?

编辑:我得到以下示例:

enter image description here

解决方案部分的内存布局为:

enter image description here

我只是不明白为什么这样显示。因此,我认为可以遵循某种算法来构建它。

3 个答案:

答案 0 :(得分:2)

该布局取决于编译器定位的ABI。您应该研究ABI的文档,以了解如何在内存中布置类。

例如,GCC使用Itanium ABI

答案 1 :(得分:0)

我将假设您得到的图认为C ++是具有附加功能的C,并从该角度对实现定义的行为进行了假设。

它正在从左到右读取 base-specifier-list ,首先是深度,并假设虚拟继承是单个指针。每个带标签的框对应于类的非静态数据成员子对象(没有子类)。未标记的框是指向虚拟基础的指针。

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

这结束了E的非虚拟基础,但是仍然有尚未存储的虚拟基础。

我们制作一个B,它具有一个非虚拟的A,并将偏移量记录在E中。 我们制作一个D,它具有一个非虚拟的B,它具有一个非虚拟的A,并将偏移量记录在E

答案 2 :(得分:0)

除标准布局类型外,它是实现定义的,也许也未指定:

对于多种继承模式,您可以使用static_cast来了解布局的方式-即使在那时也没有gaurentee:这看起来像这样:

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

免责声明:这是不安全的。