12

虚拟表如何存储在内存中?他们的布局?

例如

class A{
    public:
         virtual void doSomeWork();
};

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

A 类和 B 类的虚拟表在内存中的布局如何?

4

6 回答 6

36

对于 Linux 中的 GCC 编译器,请运行:

g++ -fdump-class-hierarchy example.h

输出是:

A 的 Vtable
A::_ZTV1A: 3u 条目
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI1A)
16 (int (*)(...))A::doSomeWork

A级
   大小=8 对齐=8
   基本尺寸=8 基本对齐=8
A (0x7fb76785a4e0) 0 几乎为空
    vptr=((& A::_ZTV1A) + 16u)

B 的 Vtable
B::_ZTV1B: 3u 个条目
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI1B)
16 (int (*)(...))B::doSomeWork

B类
   大小=8 对齐=8
   基本尺寸=8 基本对齐=8
B (0x7fb7678510d0) 0 几乎为空
    vptr=((& B::_ZTV1B) + 16u)
  A (0x7fb76785a540) 0 几乎为空
      主要用于 B (0x7fb7678510d0)

我还创建了vtable-dumper工具来列出共享对象中虚拟表的内容。使用此工具,您无需编译标头,只需在对象上运行它:

vtable-dumper SHLIB
于 2012-07-13T07:37:45.303 回答
12

正如其他人所说,这取决于编译器,而不是您在日常使用 C++ 时真正需要考虑的事情。但是,如果您只是对这个问题感到好奇,您应该阅读 Stan Lippman 的书Inside the C++ Object Model

于 2009-08-27T16:24:31.013 回答
6

内存中的 vtable 布局完全依赖于编译器;没有采取“正确”或普遍的方法。

于 2009-08-27T16:14:02.610 回答
4

正如其他人已经写的那样,没有通用的方法。(见鬼,甚至没有人强制要求使用虚拟表。)

但是,我相信它们最有可能实现为对象中某个偏移量处的隐藏指针,该对象引用函数指针表。某些虚函数的地址占据了该表中的某些偏移量。通常还有一个指向动态类型std::type_info对象的指针。

如果您对此类内容感兴趣,请阅读Lippmann 的“深入 C++ 对象模型”。然而,除非你的兴趣是学术性的(或者你正在尝试编写一个 C++ 编译器——但你不应该问),你不应该打扰。这是一个你不需要知道也不应该依赖的实现细节。

于 2009-08-27T16:22:25.247 回答
3

来自维基百科

C++ 标准并没有明确规定必须如何实现动态调度

所以答案是否定的。vtable 的布局是实现定义的。

于 2009-08-27T16:16:05.633 回答
1

有关Open Watcom类布局的非常详细的描述,请查看Class Layout notes

于 2009-08-27T21:02:58.020 回答