delphi类消息的处理机制

delphi类消息的处理机制

文章不涉及windows消息循环和更复杂的技术,只从delphi类继承及类自身的消息处理分析,是自己的学习心得和体验.

1.搜索类本身有没有处理该消息值的函数,如果有,则终止循环.循环次数:1

2.搜索父类有没有处理该消息值的函数,如果有,则终止循环.  循环次数 2

3.向父类继续搜索,直到object

4.搜索类本身在没有默认处理函数,如果有,则终止循环

5.搜索父类有没有默认处理函数

6.向父类继续搜索.直到object.(默认处理函数,object一定有)

其实,4,5,6步骤在代码实现时,只查找了一次,这要归功于vmt(虚函数表),其简化后的vmt表如下(此图仅说明原理,并不表示编译器一定也是如此实现)

 

一般而言,虚函数dispatch是不会重载的,delphi源代码中,它的实现体是汇编语言,重载这个函数没有什么实际意义了.)当然,有特殊需要或高手表演时就可以重载的.而虚函数defaulthandler是容易重载的,Tobject类中,该方法是一个空操作,在其继承类中,可以重载.

转到原题:如果某一类如Tmyclass,它与Tobject之间可以有任意多个父子类,当用Tmyclass.dispatch调用时,实际是调用的Tobject.dispatch函数,dispatch首先调用另一函数GetDynaMethod,它查询动态方法表(dmt)中是否有消息值等于传递消息结构中第一个成员的值,如果有,就调用相应的方法,如果没有,则父类的动态方法表继续查找.直到找到相应处理过程或Tobject的动态方法表为nil

:我认为,delphi中的消息过程,本身就是一个动态方法.其内存地址写入动态方法表中,如果不是这样,怎么会从dmt中查找呢,这只是个人推测.

当然,如果用getdynalmethod方法查找不到相应的处理方法时,dispatch则会调用defaulthandler函数,这时用的是虚函数表vbt,一次操作就能马上找到了.

这个消息过程,本身也体现了,vmtdmt的差别了.vmt执行函数快捷,省时,单占内存.dmt执行函数需要递归查询,效率低些.

下面是引用Nicrosoft申旻的内容:

比较一下 VMT DMT 的区别:

VMT
中的虚函数非常齐全,因此对每个虚函数的入口地址只需要简单的 [vptr + n] 的运算即可得到,但是 VMT 容易消耗内存(有冗余)。而 DMT 比较节省空间,但要定位到没有被覆盖的函数的入口地址时,将非常耗费时间。


一般情况下,几乎每个子类都要覆盖的函数/方法,就将它声明为 virtual;如果类层次很深,或子类很多,但某个函数/方法只被很少的子类覆盖,就将它声明为 dynamic
。当然,具体就需要自己把握来选择了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值