虚拟方法virtual的用法

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TFather = class
  public
    procedure Fa; // virtual;
  end;

  TChild = class(TFather)
  public
    procedure Fa; // override;
    procedure Ca;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TChild }

procedure TChild.Ca;
begin
  ShowMessage('Childer');
end;

procedure TChild.Fa;
begin
 // inherited;
end;

{ TFather }

procedure TFather.Fa;
begin
  ShowMessage('Father');
end;

procedure TForm1.Button1Click(Sender: TObject);              // C->F
var
  F: TFather;
begin
  F := TChild.Create;
  F.Fa;
 // F.Ca; //编译不过去
end;

procedure TForm1.Button2Click(Sender: TObject);              // C(F)
var
  F: TFather;
begin
  F := TFather.Create;
  TChild(F).Fa; //***  声明方法时,如果不用 virtual 和 override 关键字修饰的话
                //***  那么在子类实现时要手动的调用 inherited 才可以正确调用父
                //***  类实现的方法,但是如果使用了 virtual 和 override 的话,
                //***  则可以不用手动的调用 inherited 也能正确调用(即当按Ctrl+C
                //***  时会自动添加inherited。

  TChild(F).Ca; //虽然创建的是父类,但是强制转换后(重新设定对象范围)可以调用。
                //但是不确定是否会有意外的错误发生。
                //如果使用了关键字override,编译器会使用晚帮定,即到运行是根据实
  //际的对象来决定调用父类方法还是子类方法
  //换句话说就是使用了关键字的话,强制转换将不起作用。(起到的作用
  //只是检测到父类中是否有此方法了,有可以调用,但是调用的还是子类
  //的方法,要是没有就根本不能调用)
end;

procedure TForm1.Button3Click(Sender: TObject);              // F(C)
var
  C: TChild;
begin
  C := TChild.Create;
  TFather(C).Fa;
  //TFather(C).Ca;     //编译不过去
end;

end.

原文地址:https://www.cnblogs.com/spiritofcloud/p/3898363.html