A
class-type value is stored as a 32-bit pointer to an instance of the class,
which is called an object. The internal data format of an object resembles that
of a record. The object’s fields are stored in order of declaration as a sequence
of contiguous variables. Fields are always aligned, corresponding to an
unpacked record type. Any fields inherited from an ancestor class are stored
before the new fields defined in the descendant class.
The first
4-byte field of every object is a pointer to the virtual method table
(VMT) of the class. There is exactly one VMT per class (not one per object);
distinct class types, no matter how similar, never share a VMT. VMTs are built automatically
by the compiler, and are never directly manipulated by a program. Pointers to
VMTs, which are automatically stored by constructor methods in the objects they
create, are also never directly manipulated by a program.
The layout of a VMT is shown in the following table. At positive offsets, a VMT consists of a list of 32-bit method pointers one per user-defined virtual method in the class type in order of declaration. Each slot contains the address of the corresponding virtual method’s entry point. This layout is compatible with a C++ v-table and with COM. At negative offsets, a VMT contains a number of fields that are internal to Object Pascal’s implementation. Applications should use the methods defined in TObject to query this information, since the layout is likely to change in future implementations of Object Pascal.
|
Offset |
Type
|
Description |
|
-76 |
Pointer |
pointer to virtual method table (or nil) |
|
-72 |
Pointer |
pointer to interface table (or nil) |
|
-68 |
Pointer |
pointer to Automation information table
(or nil) |
|
-64 |
Pointer |
pointer to instance initialization table
(or nil) |
|
-60 |
Pointer |
pointer to type information table (or nil) |
|
-56 |
Pointer |
pointer to field definition table (or nil) |
|
-52 |
Pointer |
pointer to method definition table (or nil) |
|
-48 |
Pointer |
pointer to dynamic method table (or nil) |
|
-44 |
Pointer |
pointer to short string containing class
name |
|
-40 |
Cardinal |
instance size in bytes |
|
-36 |
Pointer |
pointer to a pointer to ancestor class
(or nil) |
|
-32 |
Pointer |
pointer to entry point of SafecallException
method (or nil) |
|
-28 |
Pointer |
entry point of AfterConstruction
method |
|
-24 |
Pointer |
entry point of BeforeDestruction
method |
|
-20 |
Pointer |
entry point of Dispatch method |
|
-16 |
Pointer |
entry point of DefaultHandler
method |
|
-12 |
Pointer |
entry point of NewInstance method |
|
-8 |
Pointer |
entry point of FreeInstance method |
|
-4 |
Pointer |
entry point of Destroy destructor |
|
0 |
Pointer |
entry point of first user-defined virtual
method |
|
4 |
Pointer |
entry point of second user-defined
virtual method |
|
... |
... |
... |
类类型的值存储为一个32位的指针,该指针指向类的实例即对象。对象的内部数据格式类似于记录。对象的域按照其声明的顺序存储为相邻变量的一个序列。域总是被调整排列,就象未压缩的记录类型。自祖先类中继承来的类都在后裔类定义的新的域之前被存储。
所有对象最前面的4个字节都是一个指针,该指针指向类的虚拟方法表VMT(virtual method table)。每个类(不是每个对象)有且仅有一个VMT;不同的类类型,无论多么相似,都不会共享VMT。VMT由编译器自动建立,并且决不要在程序中直接操作。指向VMT的指针在对象被创建时由构造器自动存储,也决不要在程序中直接操作。
虚拟方法表(VMT)的布局如下表。在偏移量为正数(准确地说,应是零和整数)的部分,VMT由若干32位的方法指针列表组成,类类型中每个由用户定义的虚拟方法在VMT中都以声明时的顺序排列。每个内存段中存储了相应虚拟方法入口点的地址。这一布局对C++的v-table和COM都是兼容的。在偏移量为负数的部分,VMT包含大量由Object Pascal内部实现的域。应用程序应该使用定义于TObject中的方法来查询这些信息,因为这一布局结构很可能在Object Pascal将来实现时发生改变。
|
偏移量 |
类型
|
描述 |
|
-76 |
Pointer |
指向虚拟方法表(或nil) |
|
-72 |
Pointer |
指向接口表(或nil) |
|
-68 |
Pointer |
指向自动化信息表(或nil) |
|
-64 |
Pointer |
指向实例初始化表(或nil) |
|
-60 |
Pointer |
指向类型信息表(或nil) |
|
-56 |
Pointer |
指向域定义表(或nil) |
|
-52 |
Pointer |
指向方法定义表(或nil) |
|
-48 |
Pointer |
指向动态方法表(或nil) |
|
-44 |
Pointer |
指向包含类名称的短串 |
|
-40 |
Cardinal |
实例的尺寸(以字节计算) |
|
-36 |
Pointer |
指向一个指针,该指针指向祖先类(或nil) |
|
-32 |
Pointer |
指向SafecallException方法的入口点(或nil) |
|
-28 |
Pointer |
AfterConstruction方法的入口点 |
|
-24 |
Pointer |
BeforeDestruction方法的入口点 |
|
-20 |
Pointer |
Dispatch方法的入口点 |
|
-16 |
Pointer |
DefaultHandler方法的入口点 |
|
-12 |
Pointer |
NewInstance方法的入口点 |
|
-8 |
Pointer |
FreeInstance方法的入口点 |
|
-4 |
Pointer |
Destroy析构器的入口点 |
|
0 |
Pointer |
第一个由用户定义的虚拟方法的入口点 |
|
4 |
Pointer |
第二个由用户定义的虚拟方法的入口点 |
|
... |
... |
... |