• Delphi子类调用祖父类的虚函数


    因为看Delphi书的时候,就产生了疑惑。老讲调用父类虚函数,但是万一需要调用祖父虚函数怎么办?
    后来又经常在C++里看到,就更疑惑了

    type
      TA = class
        procedure ShowMsg; virtual;
      end;
    
      TAClass = class of TA;
    
      TB = class(TA)
        procedure ShowMsg; override;
      end;
    
      TShowMsg = procedure of object;
    
      TC = class(TB)
      private
        FGrandFatherShowMsg: TShowMsg;
        procedure ShowMsg; override;
      public
        constructor Create;
      end;
    
    procedure TForm2.Button1Click(Sender: TObject);
    var
      C: TC;
    begin
      C := TC.Create;
      C.ShowMsg;
      C.Free;
    end;
        
    { TC }
    
    constructor TC.Create;
    var
      AMethod:TShowMsg;
      ACode: TMethod absolute AMethod;
      A: TA;
    begin
      inherited Create;
      A := TA.Create;
      FGrandFatherShowMsg := A.ShowMsg;
      AMethod:= FGrandFatherShowMsg;
      ACode.Data := Self;
      A.Free;
    end;
    
    procedure TC.ShowMsg;
    begin
      FGrandFatherShowMsg;
      ShowMessage('TC');
    end;
    
    { TA }
    
    procedure TA.ShowMsg;
    begin
      ShowMessage('TA');
    end;
    
    { TB }
    
    procedure TB.ShowMsg;
    begin
      inherited;
      ShowMessage('TB');
    end;


    利用了 Delphi 能够创建纯虚函数实例的特性
    记录下了TA的函数地址
    然后替换其Data的值为Self,然后在需要的时候再调用
    利用了两点:TMethod和Delphi能够创建纯虚类实例
    只是说万一纯虚的话,这个也好使

    感谢 [长春]swish

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

    另一种办法:

    type
      TBase = class
        procedure Foo; virtual;
      end;
    
      TAnsestor = class(TBase)
        procedure Foo; override;
      end;
    
      TChild = class(TAnsestor)
        procedure Foo; override;
        procedure BaseFoo;
      end;
    
    procedure TBase.Foo;
    begin
      ShowMessage('TBase');
    end;
    
    procedure TAnsestor.Foo;
    begin
      ShowMessage('TAnsestor');
    end;
    
    procedure TChild.Foo;
    begin
      ShowMessage('TChild');
    end;
    
    type
      TFoo = procedure of object;
    
    procedure TChild.BaseFoo;
    var
      Proc: TFoo;
    
    begin
      TMethod(Proc).Code := @TBase.Foo; // Static address
      TMethod(Proc).Data := Self;
      Proc();
    end;
    
    procedure TForm4.Button1Click(Sender: TObject);
    var
      Obj: TChild;
      Proc: TFoo;
    
    begin
      Obj:= TChild.Create;
      Obj.BaseFoo;
    // or else
      TMethod(Proc).Code := @TBase.Foo; // Static address
      TMethod(Proc).Data := Obj;
      Proc();
    
      Obj.Free;
    end;

    http://stackoverflow.com/questions/4662744/delphi-how-to-call-inherited-inherited-ancestor-on-a-virtual-method

    诀窍是搜索关键字“delphi inherited super parent”

  • 相关阅读:
    详细解读 DispatcherServlet 初始化过程(带时序图)
    从源码分析ContextLoaderListener的加载过程(带时序图)
    SpringMVC自带Cron定时器Demo及常见问题
    win7系统用sqlyog连接不上docker启动的mysql数据库
    使用maven-Jetty9-plugin插件运行第一个Servlet
    Maven项目+内嵌tomcat+Servlet
    Maven依赖的scope属性(附官方文档)
    使用 Intellij IDEA 新建一个 Servlet 项目
    在 Tomcat 上部署你的第一个 Servlet 应用
    关于JAVA的垃圾回收机制
  • 原文地址:https://www.cnblogs.com/findumars/p/6143097.html
Copyright © 2020-2023  润新知