zoukankan      html  css  js  c++  java
  • Delphi高手突破第二章(4),VMT与DMT

    ==============================VMT===================================

    在创建一个类的实例之后,编译器在该对象的内存空间的首4个字节安插一个指针,该指针指向的地址称为VMT(Virtual Method Table,虚方法表),这个表中放了该类的所有虚方法的入口地址。

    在Object Pascal中,所有类实例都会有这么一个指向VMT的指针。如果没有在类中声明虚方法,则该指针为nil。
    没有被派生类赋给的方法,编译器会将基类的该方法实现的入口地址填入派生类的VMT中。

    其实“指向VMT的指针”所指向的VMT,其实只是真正VMT的一部分,也就是用户定义的第一个虚方法的位置。如果以这个位置为原点,向正方向即刚才所说的VMT,而向负方向,则是语言定义的另一些信息所在地址,析构函数地址就被放在了负方向上了。所以VMT中也有析构函数,但没有出现在我们所能见到的VMT中。这样做的目的,是为了与C++以及COM的VMT相兼容。

    据观察:负方向包括7个TObject的虚函数(包括析构函数,位置-4),以及指向其它表格的指针(虚方法表, 接口表, Automation information table, 实例初始化表, 类型信息表,属性表, 方法表, DMT(动态方法表), 类名, 实例大小,指向祖先类指针,安全异常指针)

    ==============================DMT====================================

    VMT的-48处是一个指向DMT的指针,它与VMT有什么关系?

    派生类的虚方法表完全继承了基类的虚方法表,只是将被覆盖的虚方法地址变了。基类和每个派生类都有一份自己的虚方法表。可以想象,随着类层次的扩展,虚方法将耗费非常大的内存空间。为了防止这种情况,Object Pascal引入了“dynamic”的概念。dynamic和virtual方法实现相同的功能,只有声明的关键字不同。被声明为dynamic的方法,其入口地址将被放在DMT中。

    VMT和DMT的区别在于:对于派生类没有覆盖的方法,这些方法的入口地址不会出现在DMT中,编译器要通过基类的信息来寻找它们的入口地址。

    DMT中不会出现没有被派生类覆盖的基类dynamic方法,因此DMT会比VMT节省空间,但是DMT中对基类的动态方法的寻址不是直接进行的,因此dynamic要比virtual要慢一些。当基类有许多虚方法,而派生类只覆盖很少几个时,区别尤其明显。当派生层次越来越深,派生数量越来越多时,DMT就能节省更多的内存空间。virtual与dynamic的区别仅在于编译器采用不同的晚绑定策略而已,对于程序员而言,它们的功能相同。

    几乎每个派生类都要覆盖的方法,将它声明为virtual;
    如果层次很深,或者派生类很多,但某个方法只被很少的派生类赋给,则声明为dynamic。

    另外需要注意的是,只有VMT才与C++、COM的vtable兼容。如果需要这样的兼容性时,只能使用virtual。

  • 相关阅读:
    java操作生成jar包 和写入jar包
    jboss配置jndi连接池
    windows 域的LDAP查询相关举例
    LDAP error Code 及解决方法
    HDU 6417
    CF1299D Around the World
    codechef Chef and The Colored Grid
    Educational Codeforces Round 82 (Rated for Div. 2)
    CF1237F Balanced Domino Placements
    CF1254E Send Tree to Charlie
  • 原文地址:https://www.cnblogs.com/findumars/p/2629563.html
Copyright © 2011-2022 走看看