继承类的内存布局

owa*_*agh 15 c++ layout inheritance

我很想知道如何将类安排在内存中.具有继承和虚函数.

我知道这不是由c ++语言标准定义的.但是,是否有任何简单的方法可以通过编写一些测试代码来了解您的特定编译器如何实现这些?

编辑: - 使用以下一些答案: -

#include <iostream>

using namespace std;

class A {
  public:
    int a;
    virtual void func() {}
};

class B : public A {
  public:
    int b;
    virtual void func() {}
};

class C {
  public:
    int c;
    virtual void func() {}
};

class D : public A, public C {
  public:
    int d;
    virtual void func() {}
};

class E : public C, public A {
  public:
    int e;
    virtual void func() {}
};

class F : public A {
  public:
    int f;
    virtual void func() {}
};

class G : public B, public F {
  public:
    int g;
    virtual void func() {}
};

int main() {
  A a; B b; C c; D d; E e; F f; G g;
  cout<<"A: "<<(size_t)&a.a-(size_t)&a<<"\n";
  cout<<"B: "<<(size_t)&b.a-(size_t)&b<<" "<<(size_t)&b.b-(size_t)&b<<"\n";
  cout<<"C: "<<(size_t)&c.c-(size_t)&c<<"\n";
  cout<<"D: "<<(size_t)&d.a-(size_t)&d<<" "<<(size_t)&d.c-(size_t)&d<<" "<<(size_t)&d.d-    (size_t)&d<<"\n";
  cout<<"E: "<<(size_t)&e.a-(size_t)&e<<" "<<(size_t)&e.c-(size_t)&e<<" "<<(size_t)&e.e-    (size_t)&e<<"\n";
  cout<<"F: "<<(size_t)&f.a-(size_t)&f<<" "<<(size_t)&f.f-(size_t)&f<<"\n";
  cout<<"G: "<<(size_t)&g.B::a-(size_t)&g<<" "<<(size_t)&g.F::a-(size_t)&g<<" "    <<(size_t)&g.b-(size_t)&g<<" "<<(size_t)&g.f-(size_t)&g<<" "<<(size_t)&g.g-(size_t)&g<<"\n";
}
Run Code Online (Sandbox Code Playgroud)

输出是: -

A: 8
B: 8 12
C: 8
D: 8 24 28
E: 24 8 28
F: 8 12
G: 8 24 12 28 32
Run Code Online (Sandbox Code Playgroud)

所以所有类都有一个大小为8的loc 0的v-ptr .D在16位有另一个v-ptr.同样对于E. G似乎也有16位的v-ptr,尽管从我(有限的)理解我会已经猜到它有更多.

Mys*_*ial 16

一种方法是打印出所有成员的抵消:

class Parent{
public:
    int a;
    int b;

    virtual void foo(){
        cout << "parent" << endl;
    }
};

class Child : public Parent{
public:
    int c;
    int d;

    virtual void foo(){
        cout << "child" << endl;
    }
};

int main(){

    Parent p;
    Child c;

    p.foo();
    c.foo();

    cout << "Parent Offset a = " << (size_t)&p.a - (size_t)&p << endl;
    cout << "Parent Offset b = " << (size_t)&p.b - (size_t)&p << endl;

    cout << "Child Offset a = " << (size_t)&c.a - (size_t)&c << endl;
    cout << "Child Offset b = " << (size_t)&c.b - (size_t)&c << endl;
    cout << "Child Offset c = " << (size_t)&c.c - (size_t)&c << endl;
    cout << "Child Offset d = " << (size_t)&c.d - (size_t)&c << endl;

    system("pause");
}
Run Code Online (Sandbox Code Playgroud)

输出:

parent
child
Parent Offset a = 8
Parent Offset b = 12
Child Offset a = 8
Child Offset b = 12
Child Offset c = 16
Child Offset d = 20
Run Code Online (Sandbox Code Playgroud)

所以你可以在这里看到所有的偏移量.您会注意到偏移0处没有任何内容,因为这可能是指向vtable的指针所在的位置.

另请注意,继承的成员在Child和Parent中具有相同的偏移量.


Xeo*_*Xeo 8

Visual Studio atleast有一个隐藏的编译器选项 /d1reportSingleClassLayout(从~32:00开始).

用法:/d1reportSingleClassLayoutCLASSNAME编译器开关之间不应有空格CLASSNAME(显然用你感兴趣的类的名称替换它).