网站公告列表

  没有公告

加入收藏
设为首页
联系站长
您现在的位置: 网络学院 >> 程序设计 >> Delphi编程 >> 文章正文
  访问祖先类的虚方法            【字体:
访问祖先类的虚方法
作者:佚名    文章来源:不详    点击数:    更新时间:2007-9-12    

访问祖先类的虚方法

问题提出

       在子类覆盖的虚方法中,可以用inherited调用父类的实现,但有时候我们并不需要父类的实现,而是想跃过父类直接调用祖先类的方法。
正在装载数据……

举个例子,假设有三个类,实现如下:

type

  TClassA = class

    procedure Proc; virtual;

  end;

 

  TClassB = class(TClassA)

    procedure Proc; override;

  end;

 

  TClassC = class(TClassB)

    procedure Proc; override;

  end;

 

implementation

 

procedure TClassA.Proc;

begin

  ShowMessage('Proc of class A');

end;

 

procedure TClassB.Proc;

begin

  ShowMessage('Proc of class B');

end;

 

procedure TClassC.Proc;

begin

  ShowMessage('Proc of class C');

end;

用如下代码调用虚方法Proc

var

  C: TClassA;

begin

  C := TClassC.Create;

  C.Proc;

  C.Free;

end;

我们知道最终调用的是TClassC.Proc;如果在TClassC.Proc中加上Inherited,则TClassB.Proc可以得到调用;但是现在,若想在TClassC.Proc中直接调用TClassA.Proc,该怎么办呢?

解决之道

如果是C++,只需要这样写:TClassC::Proc

Delphi却没有办法做到,Delphi不允许我们跃级调用祖先类的方法。尽管如此,还是能从另一个角度来寻求解决的办法。

解决之道就是VMT,每一个类就是一个指向VMT的指针,而VMT的作用其实就是用来保存虚方法的。在VMT的正方向上,列着从祖先类起的所有虚方法,只需要偏移TClassAVMTProc,然后调用之即可。

来看看这个问题是怎么得解决的:

procedure TClassC.Proc;

type

  TProc = procedure of object;

var

  M: TMethod;

begin

  M.Code := PPointer(TClassA)^;

  M.Data := Self;

  TProc(M)();

  ShowMessage('Proc of class C');

end;

执行一次调用,可以看到先弹出:Proc of class A;然后弹出:Proc of class C。这说明TClassA.ProcTClassC.Proc中被调用到了。

 

请注意上面的代码,TClassAVMT上的第0偏移就是Proc的地址,而TClassA继承自TObjectTObject本身也有一些虚方法的,比如AfterConstruction,那么这些是存放在哪里呢?

秘密就在VMT的负偏移上,在System单元中声明了虚表的结构偏移,在负方向上有AfterConstruction的进入点。需要指出的是,System单元中声明了结构偏移正方向的几个已经过时了,第0偏移(vmtQueryInterface)不是存放QueryInterface,而是存放第一个虚方法(除TObject外)。

下面是从帮助上拷下来的VMT布局:

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

后记

       利用虚表调用虚方法的做法,终究不是安全的,因为Borland(CodeGear)没有向你保证每一个Delphi版本的VMT布局都是一样的。

       因此,使用这个方法的时候要慎之又慎。




本文来源:http://blog.csdn.net/linzhengqun/archive/2007/08/23/1755493.aspx
站内文章搜索 高级搜索
文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
     在delphi中使用xml文档有…
     初探delphi 7 中的插件编…
     delphi 2006(dexter) & …
     获得windows的版本信息。
     “序列号输入助手”源代…
     rs232串口通讯模块
     ado方式下判断数据表是否…
  • java类的反射机制

  • 编译期判断类的继承性

  • Ajax - javascript之实现…

  • VB.NET类的总结(一)

  • servlet 定时操作,定时访问…

  • 演示java面向对象的核心特性…

  • JSP 调用类的方法

  • java.lang.ThreadLocal类的实…

  • java虚拟机类的加载顺序

  • MyClass.class和初始化类的研…

  •   网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    网络学院©2007 www.23book.net
    为您提供web编程,vb编程,vc编程,服务器架设管理,数据库设计等方面的知识 站长:David