Every Delphi class is defined internally by its vmt—​its virtual-method table. The vmt contains a list of pointers to a class’s virtual methods. It also contains some other class-specific information, including the name, the size, a reference to the parent’s vmt, and run-time type information. A class reference (i.e., a TClass value) is a pointer to the class’s vmt, but not to the start of the table. Instead, it is a pointer to the entry for the first virtual method after the methods introduced inTObject. Virtual methods declared in TObject reside at negative offsets from the vmt pointer.

Virtual methods

The main purpose of the vmt is to hold pointers to a class’s virtual methods. Instead of calling a method directly, the compiler will generate an indirect method call. A program will use a known index value to find the address of a method.

For example, if a program has a TList variable, it may hold a reference to a TList object, but it may also hold a reference to aTObjectList, as shown in Listing 1. When the program calls theNotify method via that variable, the compiler cannot know in advance whether to call the base TList​.Notify method or to call the overridden method in TObjectList because the compiler does not know what the run-time type of the object is. Instead, the compiler generates code to look at the second entry in the vmt, which is the entry reserved for the Notify method. That method will be at that entry no matter how far down the inheritance chain you go from theTList base.

The first field of any object instance contains the object’s run-time type as a class reference, which as I noted above is just a pointer to the class’s vmt. See Figure 1. To call a virtual method, then, a program first dereferences the object reference to get the vmt pointer, and then it dereferences that pointer at the offset corresponding to the desired method to determine the address of that method. At that point the program is ready to jump to that address, just as it would have done all along if the method were not virtual. If the method had not been virtual, then its address would have been compiled directly into the code at the place it was called. The program would not have had to look up the address in the method table.

Listing 1

Code to instantiate two TObjectLists

var
  ObjList1, ObjList2: TList;
begin
  ObjList1 := TObjectList.Create(True);
  ObjList2 := TObjectList.Create(True);
end;

Figure 1

Illustration of the object and vmt layouts resulting from the code of Listing 1. Note that both TObjectList instances point to thesame vmt.

Non-method contents of the vmt

In addition to the pointers to virtual methods, the vmt contains other class-specific information at offsets even farther negative than theTObject methods, as shown in Table 1.

Table 1

Non-method vmt offsets, in bytes, according to the Delphi 2005 implementation

Name Offset
vmtSelfPtr –76
vmtIntfTable –72
vmtAutoTable –68
vmtInitTable –64
vmtTypeInfo –60
vmtFieldTable –56
vmtMethodTable –52
vmtDynamicTable –48
vmtClassName –44
vmtInstanceSize –40
vmtParent –36
vmtParent

The table entry at this offset holds a pointer to the vmt of the class’s parent. For TObject, which has no parent, this field contains nil.

vmtInstanceSize

This entry holds the size, in bytes, of an instance of the class. This field gets used by TObject​.NewInstance, which allocates memory for a new instance of a class.

vmtClassName

At this offset is a PShortString value with the name of the class. The TObject​.ClassName method returns this string.

vmtDynamicTable

Here resides a pointer to a list of pointers to the class’s dynamic methods (as opposed to its virtual methods, which are in the vmtitself). The list also contains pointers to all a class’s message handlers, which means the Dispatch method relies on this list, too.

vmtMethodTable

This entry holds a pointer to method-name information, which theTObject​.MethodName and MethodAddress methods use to fetch their results.

vmtFieldTable

This entry is to field addresses as vmtMethodTable is to method addresses.

vmtTypeInfo

At this offset, the table holds a pointer to the class’s run-time type information. Recall that to have rtti, a class must have been compiled in the $M+ compiler state or descend from a class compiled in that state (such as TPersistent). Other classes will just contain nil in this field.

vmtInitTable

TObject​.CleanupInstance uses the data structure pointed to at this offset to know which of an object’s fields need to be cleaned up specially while the object is being destroyed. Those fields are of the same types as the ones that get cleaned up when a dynamic array gets freed.

vmtAutoTable

At this offset is a pointer to a class’s automation table, which holds a list of method entries, including their names, dispids, and parameter lists. The TAutoObject class uses this table to implement the IDispatch interface. The compiler generates the list based on the methods declared in the class’s automated section.

vmtIntfTable

The value at this offset provides the result for the TObject​.GetInterfaceTable method, which is used in two places.

  1. The first is in the implementation of GetInterfaceEntry, which is used most often to implement IUnknown​.QueryInterface. The method searches the interface table of the class and of any parent classes, if necessary, for an entry with a matching guid.

  2. GetInterfaceTable also occurs in the implementation ofInitInstance. That method sets all a new object’s fields to all-bits-zero, but then it uses the interface table to initialize any hidden interface-method-table pointers to appropriate values. I describe those hidden pointers in a separate article.

vmtSelfPtr

This entry marks the end of the vmt. It holds a pointer back to the beginning of the table. For example, at the vmtSelfPtr offset ofTButton’s vmt will be the value TButton.

Deprecated vmt-offset constants

When using some of the vmt-offset constants, such as vmtDestroy orvmtDefaultHandler, the compiler may issue a warning that the constants are deprecated. In that case, use the vmtoffset assembler keyword with the name of the method you need.

http://pages.cs.wisc.edu/~rkennedy/vmt#vmtSelfPtr

Delphi的VMT的结构图,很清楚的更多相关文章

  1. delphi xe5 fastreport4.14 中文很多时换行不正确

    用一般的frxMEMOview 中文换行是瞎换,缺少数据,换成frxrichview 即可, frxrichview 使用注意点 1).Delphi中文很多时换行不正确 2).要在窗体上拖一个frxr ...

  2. Delphi 的多线程使用已经很简单了

    先看一个非多线程的例子, 代码执行时不能进行其它操作(譬如拖动窗体): {自定义方法: 在窗体上绘制...} procedure MyMethod; var   i: Integer; begin   ...

  3. Delphi 编写DLL动态链接库文件的知识和样例(有详细步骤,很清楚)

    一.DLL动态链接库文件的知识简介: Windows的发展要求允许同时运行的几个程序共享一组函数的单一拷贝.动态链接库就是在这种情况下出现的.动态链接库不用重复编译或链接,一旦装入内存,Dlls函数可 ...

  4. delphi 10 seattle 安卓服务开发(一)

    从delphi 开始支持安卓的开发开始, 安卓service 开发一直都是delphier 绕不过去的坎, 以前也有开发service  的方法,但是都是手工处理启动文件,而且要修改很多东西,基本上成 ...

  5. Delphi在创建和使用DLL的时候如果使用到string,请引入ShareMem单元

    当使用了长字符串类型的参数.变量时,如string,要引用ShareMem. 虽然Delphi中的string功能很强大,但若是您编写的Dll文件要供其它编程语言调用时,最好使用PChar类型.如果您 ...

  6. Delphi容器类之---TList、TStringList、TObjectList,以及一个例程的代码分析

    转载自:http://blog.csdn.net/jqandjq/article/details/5429137 看了这里标题,大家可能以为我会谈TListBox控件,那就错了.我要谈的是Delphi ...

  7. Delphi DLL的创建、静态及动态调用

    转载:http://blog.csdn.net/welcome000yy/article/details/7905463 结合这篇博客:http://www.cnblogs.com/xumenger/ ...

  8. 使用delphi+intraweb进行微信开发3—微信消息处理

    示例代码已经放出!请移步使用delphi+intraweb进行微信开发1~4代码示例进行下载,虽为示例代码但是是从我项目中移出来的,封装很完备适于自行扩展和修改. 在第二讲使用delphi+intra ...

  9. Delphi XE5 常见问题解答

    Delphi XE5 常见问题解答 有关于新即时试用的问题吗?请看看 RAD Studio 即时试用常见问答. 常见问题 什么是 Delphi? Embarcadero? Delphi? XE5 是易 ...

随机推荐

  1. 转载python并行运算实例

    Python的并发处理能力臭名昭著.先撇开线程以及GIL方面的问题不说,我觉得多线程问题的根源不在技术上而在于理念.大部分关于Pyhon线程和多进程的资料虽然都很不错,但却过于细节.这些资料讲的都是虎 ...

  2. 浅谈MySql的存储引擎(表类型) (转)

    什么是MySql数据库 通常意义上,数据库也就是数据的集合,具体到计算机上数据库可以是存储器上一些文件的集合或者一些内存数据的集合. 我们通常说的MySql数据库,sql server数据库等等其实是 ...

  3. NOI2007 生成树计数

    题目 首先我要吐槽,这题目就是坑,给那么多无用的信息,我还以为要根据提示才能做出来呢! 算法1 暴力,傻傻地跟着提示,纯暴力\(40\)分,高斯消元\(60\)分. 算法2 DP!一个显然的东西是,这 ...

  4. [置顶] 让金融互联网-P2P网贷融资量增长10倍的广告宣传公益活动

    我想做一件什么事?一个公益活动,所有资料都会共享出来--- 再次声明:这是一次公益,所有资料会公开. 我正在做一点事:收集各个P2P信贷公司(包括线上线下的),然后给线上P2P信贷公司做营销策略,教他 ...

  5. 设计模式(Abstract Factory)抽象工厂

    1. 需求: 设计一个电脑组装程序,对于组装品牌电脑. 用零件组装(主板.硬盘.显示器)由品牌提供的所有. 让我们组装一台联想电脑,板子.由联想提供. (眼下仅仅有Lenovo和Dell两种品牌) 2 ...

  6. vi命令提示:Terminal too wide

    putty: 在我的电脑上,缺省的设置是这样的: localhost:~ eygle$ stty -aspeed 9600 baud; 51 rows; 171 columns; 在远程编辑文件时,减 ...

  7. 从M个数中随机选出N个数的所有组合,有序,(二)

    这就是数学中的 A m n 的选取. 共有   m!/n!种可能.. 同样举一个例子吧.. 从12345这五个数字中随机选取3个数字,要求选出来的这三个数字是有序,也就是说从12345中选出来的是12 ...

  8. 关于android多点触控

    最近项目需要一个多点触控缩放的功能.然后上网查了下资料 总结一下: 首先android sdk版本很重要,比如你在AndroidManifest.xml中指定android:minSdkVersion ...

  9. clearcase常用命令

    版本控制工具学习 http://www.itpxpj.com/course.do?method=getAllCourseInFront&classTypeId=21 1.[ClearCase] ...

  10. 重操JS旧业第七弹:面向对象与对象创建

    JS是一种完全面向对象的程序设计语言,在面向对象处理方面,具有多种多样的实现方式,加之对象成员的动态性使得这门语言更加灵活:而js对象成员动态性也是创建和扩展对象的有力方式. 1 对象成员动态性 属性 ...