zoukankan      html  css  js  c++  java
  • Delphi 系统[24]关键字和保留字 virtual、dynamic、abstract、inline、static

    Delphi 系统[24]关键字和保留字  virtual、dynamic、abstract、inline、static - 类方法类型

    1、定义:

    • virtual :虚拟方法可以被子类覆写(覆盖),虚拟方法可以加快调用速度,但浪费内存。
    • dynamic :动态方法可以被子类覆写,动态方法可以节省内存,但调用速度没有虚拟方法快。
    • abstract :抽象方法可以被子类覆写,abstract 关键字必须与 virtual 或dynamic 关键字同时使用。包含“抽象方法”的类称为“抽象类”。抽象类可以被实例化,但实例化的对象不能调用抽象方法,否则会抛出异常。
    • inline :定义内联函数或内联汇编代码,内联函数类似于宏,编译器在编译程序时,会将内联函数的代码直接搬到调用者的代码里面去,作为调用者的一部分,也就不存在调用内联函数的说法了,直接就是一行行代码。内联函数一般是体积较小且被频繁调用的函数。内联函数可以提高代码的执行效率。如果没有定义内联函数,则编译器会自己判断将那些函数作为内联函数处理,以便提高程序的执行效率,所以一般情况下我们不需要手动指定内联函数。内联说明对于编译器来说只是一种建议,编译器可以忽略这个建议,如果我们指定了内联函数而编译器觉得不合适,那么编译器可以拒绝将指定的函数内联。内联函数不是纯粹的函数,因此不能递归调用。

    2、示例:

    { 虚拟方法 }
    TObject = class
    public
      procedure Dispatch(var Message); virtual;
      destructor Destroy; virtual;
    end;
    
    ---------------------------------------------------------------------------------------
    { 动态方法 }
    TCustomForm = class
    protected
      procedure DoHide; dynamic;
      procedure DoShow; dynamic;
    end;
    
    ---------------------------------------------------------------------------------------
    { TStrings 中的抽象方法 }
    TStrings = class
    protected
      function Get(Index: Integer): string; virtual; abstract;{ 这里只需要定义,具体功能靠子类去实现 }
      function GetCount: Integer; virtual; abstract; { 这里只需要定义,具体功能靠子类去实现 }
    end;
    
    --------------------------------------------------------------------------------------
    { 内联函数 inline}
    function Test(S: string): string; inline;
    begin
      Result := '显示结果:' + S;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Caption := Test(Caption);
      { 此处调用了内联函数,所以,在编译时,此处的代码就被改成了 Caption := '显示结果:' + Caption; 直接将内联函数的代码搬过来进行编译 }
    end;
    

    3、关于 virtual 和 dynamic 方法的一些说明:

    要使方法虚拟或动态,请在其声明中包含virtual或dynamic指令。与静态方法不同,虚拟方法和动态方法可以在子类中重写。调用重写的方法时,方法调用中使用的类或对象的实际(运行时)类型(而不是声明的变量类型)决定要激活的实现。

    要重写方法,请使用override指令重新声明它。重写声明必须在其参数的顺序和类型以及结果类型(如果有)上与祖先声明匹配。

    在以下示例中,TFigure中声明的Draw方法在两个子类中被重写:

    type
      TFigure = class
        procedure Draw; virtual;
      end;
      TRectangle = class(TFigure)
        procedure Draw; override;
      end;
      TEllipse = class(TFigure)
        procedure Draw; override;
      end;
    

    给定这些声明,下面的代码说明了通过实际类型在运行时发生变化的变量调用虚拟方法的效果。

    var
      Figure: TFigure;
    begin
      Figure := TRectangle.Create;
      Figure.Draw;  // calls TRectangle.Draw
      Figure.Destroy;
      Figure := TEllipse.Create;
      Figure.Draw;  // calls TEllipse.Draw
      Figure.Destroy;
    end; 

    只能重写虚拟方法和动态方法。但是,所有方法都可以重载;请参阅重载方法。

    虚拟与动态:

    • 虚拟方法和动态方法在语义上是等价的。它们只是在运行时方法调用调度的实现上有所不同。虚拟方法优化速度,而动态方法优化代码大小。
    • 一般来说,虚拟方法是实现多态行为最有效的方法。当基类声明许多可重写的方法,这些方法由应用程序中的许多子类继承,但只是偶尔被重写时,动态方法非常有用。

    注:只有在有明显的、可观察到的好处时才使用动态方法。通常,使用虚拟方法。  

    4、其他,请参考:链接

      

    创建时间:2021.08.16  更新时间:

    博客园 滔Roy https://www.cnblogs.com/guorongtao 希望内容对你所有帮助,谢谢!
  • 相关阅读:
    router.beforeEach、路由元信息、导航守卫与函数式编程
    C++传递不定参函数
    函数式编程-compose与pipe
    玩转redux--从会用到庖丁解牛
    redux沉思录:基于flux、状态管理、函数式编程的前端状态管理框架
    Laravel 框架集成 UEditor 编辑器的方法
    i18n实现前端国际化(实例)
    laravel获取当前认证用户登录
    larave5.6 引入自定义函数库时,报错不能重复定义
    2019教师证教材资料
  • 原文地址:https://www.cnblogs.com/guorongtao/p/15146317.html
Copyright © 2011-2022 走看看