zoukankan      html  css  js  c++  java
  • Delphi多态性的实现

    多态性的概念:
    很通俗地讲,多态性是指可以将子对象赋值给父对象的技术,可以通过父对象调用子对象从父对
    象继承并覆盖了的虚方法。或者说,多态性是可以让父对象具有不同行动方式的技术。
    注意上面一句话包含了两个特性:
    (1)可以将子对象赋值给父对象的技术。
    (2)可以通过父对象调用子对象从父对象继承并覆盖了的虚方法。通过父对象调用子对象的虚方
    法时,执行的是子对象覆盖后的代码,而不是父对象实现该虚方法的代码。

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    数据相关 字样不是真的只数据,而是域(Field)、方法地址表...........

    对象中的相关数据有域(Field),可能有接口地址表、....

    类的数据相关有某某表地址入口,如此图

    这幅图只供理解参考,与真实的还是有偏差

     

    Var 

      D:TD;//D定义为TD类的变量;

    此图仅供参考,可能理解不对!

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     c++语言虚函数实现多态的原理(更新版) - coding小菜鸟 - 博客园  https://www.cnblogs.com/xgmzhna/p/10934562.html

    ---------

    初学Delphi的可以多去万一博客,想提高Delphi的也可以看万一博客

    万一博客中有用到多态:关于类的入门的例子(5): override - 万一 - 博客园  https://www.cnblogs.com/del/archive/2007/12/17/1002959.html

     -------

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    请参考:Delphi 类与对象内存结构浅析(上)_starsky2006的专栏-CSDN博客  https://blog.csdn.net/starsky2006/article/details/5497082

                 Delphi 类与对象内存结构浅析(下)_starsky2006的专栏-CSDN博客  https://blog.csdn.net/starsky2006/article/details/5497113

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    我们知道,TObject 是所有类的基本类,也就是说,所有类都直接或者间接派生于TObject。尽管
    在Delphi 中可以定义不从TObject 派生的类,但是这样的方式已经很少使用了,我们不再讨论它。因
    此,TObject 是非常重要的。它可是VCL 的命根子。
    我们知道,一个TObject 的实例:Object(对象),实际上是一个4 字节的指针,该指针指向对象
    的实际数据区(Object Data)。那么这个“对象数据区”到底是怎么回事呢?对象的字段、方法、属性、
    事件这些对象数据在“对象数据区”中究竟怎么组织、如何存取呢?
    这的确是设计和实现VCL 架构的一个根本性问题,是命根子的命根子。
    原来,这个对象数据区是划分为很多个小区域的。这些区域分为两个部分:
    (1)头4 个字节存放一个指针,该指针指向另一个地址区域。
    (2)其余小区域分别存储对象的各种数据成员(即字段,不包括方法。方法的入口地址被定义在
    另一个内存表里,虚拟方法表中有一个指针指向该表)。
    头4 个字节的指针指向的另一个地址区域是干嘛的呢?它就是我们常常听人说起的大名鼎鼎的
    “虚拟方法表(Virtual Method Table,VMT)”!虚拟方法表又被划分为很多个大小为4 字节的小区域,
    每个区域存放一个指针,每个指针对应一个虚拟方法的入口地址。
    接下来的众多小区域用来存放字段、属性值和所有非虚方法(注意这里用的是“非虚方法”而不
    是“非虚拟方法”,本节后面要详细讲述其中来由)的入口地址。
    由以上可见,非虚方法成员的存取是相对简单的,而虚方法的寻址和调用则相对复杂得多。所以,
    在本节中,我们重点要搞清楚的是虚拟方法表——VMT。

    -------------------------

    1. VMT 的结构图
    仔细观察图5-2 可以看到:一个对象(Object)指针指向一个对象数据区(Object Data);对象数
    据区的头4 个字节存放了一个指针,该指针再指向虚拟方法表(VMT)。


    图5-2 VMT 结构图
    一个虚拟方法表从指针所指地址的负偏移–76 处开始,长度动态分配(由虚拟方法的个数确定)。
    虚拟方法表被分为很多小段,每段占据4 个字节,也就是众多指针。每个指针指向一个虚拟方法的入
    口地址。
    很显然,有了一个对象指针,按图索骥,是一定可能寻址到该对象一个指定的虚拟方法,从而调
    用执行这个虚拟方法。
    上面的分析很对人胃口,一下子就让人明白了VMT 是个什么东西。不过要彻底弄清VMT,它却
    又露出另外一张面孔,可见,实际上并不是那么简单的。所以我还想说的是:
    (1)VMT 还可以细分为两个区域,即基础信息区和用户定义虚拟方法区。
    (2)VMT 对应于类而不是对象。
    VMT 的负偏移区(–76~0)是基础信息区,存储了基础性数据(如实例大小)、基础性数据(如
    接口表、运行时类型信息表、字段表、方法表、类名和父类虚拟方法表等)的指针和所有基础性虚拟
    方法(这些虚拟方法都是在类TObject 中定义的,如AfterConstruction、BeforeDestruction、DefaultHandler、
    Destroy 等)的指针,所以基础信息区并不全是指针列表。这个区域所存放的数据和指针主要是用来帮
    助实现对象的构造和析构、运行时类型信息存取、字段和方法解析等。基础信息区的大小是固定的。
    正偏移区(从0 开始)是用户定义的虚拟方法(即所有非TObject 定义的虚拟方法)所在区域,
    每4 个字节存储一个用户定义的虚拟方法指针。这些虚拟方法不光是指在本类定义的,还包括从
    TObject 一直到本类的所有中间类定义的所有虚拟方法。因此,这个区的大小是根据虚拟方法的个数决定的,不像基础信息区有固定的值。

    不同的类总是具有独立的VMT,即使这些类有继承关系或者非常近似。也就是说,VMT 是根据
    类的定义来生成的,跟类的实例没有关系。TComponent 和TControl 因为是两个不同的类,因此,它
    们的VMT 也是毫不相关的。
    在前面章节中我们提到了类引用类型(Class reference)。一个对象的类引用可以通过调用System
    单元实现的TObject.ClassType 方法来获得:

    可见,类引用实际上就是指向VMT 的指针。也就是说,类引用和VMT 有惟一对应关系。
    Delphi 中的VMT 和C++、COM 中的VMT 是兼容的,具有类似的结构。在将来版本的Delphi 中,
    VMT 的结构可能会作一定的调整,所以一般不要直接通过地址操作VMT,而代之以类和对象的方法、
    属性来存取。
    2. VMT 的产生
    VMT 是由编译器为程序中每个要用到的类自动生成的。VMT 对应相应的类而不是类实例。即是
    说,在没有创建一个类的任何实例时,该类的VMT 已经由编译器生成了,就等着一些指针去指向它。
    如果一个类TParent 定义了一个虚拟方法F,并且实现了部分功能;然后有一个类TChild 派生于
    TParent,并覆盖了虚拟方法F,做了附加功能实现。这时候编译器如何编译这个方法TChild.F,并添
    加到VMT 中间呢?是不是要编译出两个方法即TParent.F 和TChild.F,生成两个指针加入VMT 呢?
    不是的,编译器会将两个方法合成一个F,最终只产生一个指针并加入VMT。也就是说,TParent 和
    TChild 各自的VMT 都有F 的指针,互不相关。
    在调用构造函数创建一个对象时,对象数据区(Object Data)的头4 个字节被分配给一个指针,
    然后,该指针被定向到在构造对象前就已经生成的VMT 上。从而赋予对象调用虚拟方法的能力。
    3. virtual 方法和dynamic 方法的区别
    在“类和类成员”一节中,我们讲了有两类虚方法:虚拟方法(virtual)和动态方法(dynamic)。
    它们在功能上没有区别,都是为了实现子类覆盖。区别是在调用流程上。
    前面说了“非虚方法”和“非虚拟方法”是有区别的,原因就是其中还夹了个动态方法的问题。
    在上面的内容中,我们对动态方法的管理和调用只字未提,只是为了避免同时端出太多话题,从
    而偏离主题,影响我们对VMT 的总体理解。不是有所谓“话分多头,各表一枝”嘛!
    从上述VMT 的知识可以知道,virtual 方法被全部列入了VMT 的正偏移区,当一个对象请求调用
    virtual 方法时,可以在类的VMT 中直接寻址,然后马上调用。但是调用一个dynamic 方法就没有这么
    便宜了。

  • 相关阅读:
    JavaWeb chapter 8 过滤器
    JavaWeb Chapter 7 监听器
    JavaWeb chapter6 对象作用域
    JavaWeb chapeter 5 Web应用程序状态管理
    JavaWeb chapter 4 Servlet处理HTTP请求
    JavaWeb chapter3 Servlet处理HTTP响应
    JavaWeb chapter 2 Servlet
    蒙版
    CSS样式,雪碧,图片替换,渐变小析
    本地存储之简单存储
  • 原文地址:https://www.cnblogs.com/dmqhjp/p/14898974.html
Copyright © 2011-2022 走看看