C++中的对象内存布局以及它的结构如何依赖于大多数平台

Cpp*_*ter 0 c++ oop this vtable

我在C++中有两个类:

class Base
{
  int baseField;
 public:
  Base();
  ~Base();
  T BaseMethod();
  virtual SomeMethod()=0;
};

class Derived : public Base
{
  int derivedField;
 public:
  Derived()
  ~Derived();
  T DerivedMethod();
  virtual SomeMethod() {...}; // Some implementation
};
Run Code Online (Sandbox Code Playgroud)

我的问题是它是如何在内存中表示的,即这个类的指针,vptr(vtable)字段方法指针在哪里.好的,它依赖于编译器,但有一些不成文的标准.我对Visual Studio和gcc编译器最感兴趣.

[编辑:我用一个虚拟方法来改进示例,之前没有任何虚拟]

有没有一些关于这个主题的书籍

Kon*_*lph 11

您的类没有虚拟表指针,因为它们没有虚函数.

就像你说的那样,即使它们有,C++也没有指定如何实现虚函数 - 每个编译器都可以不同的方式实现,不需要存在vtable.

在实践中,理智的实现(对于单继承)是在类的开头有一个虚拟表指针,之后是普通的类成员.没有"方法指针"这样的东西 - 正常的成员函数在编译时被解析,虚函数按照它们的声明顺序在vtable中有它们的指针.

这是一个示例布局:

struct Base {               + Base ------------+     + Base vtable ----+
    virtual void foo();     | * vptr        ---|---> | * void (*foo)() |
    T bases_field;          | * base_field     |     +-----------------+
};                          +------------------+

struct Derived {            + Derived ---------+     + Derived vtable -+
    T derived_field;        | * CBase instance |---> | * void (*foo)() |
};                          | * derived_field  |     +-----------------+
                            +------------------+
Run Code Online (Sandbox Code Playgroud)

(不要缩放内存中占用的字节数.)

因此,每个实例都包含一个指向虚拟表的指针.每个类只有一个虚拟表.即在所有实例之间共享一个实例,CBase并在所有实例之间共享CDerived.