继承、虚方法、override、reintroduce
类的继承的例子
Object Pascal 支持继承与虚方法。 下例中 TDog 继承自 TAnimal:
TDog 是子类(派生类) TAnimal 是父类(祖先类)
program AnimalDemo;
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
{$codepage utf8}
uses SysUtils;
type
// 动物父类
TAnimal = class
procedure Cry; virtual; // 虚方法:动物叫
end; // 类定义结束,只有 end;
// 狗子类,继承动物并重写叫声
TDog = class(TAnimal)
procedure Cry; override;
end;
procedure TAnimal.Cry;
begin
WriteLn('动物发出叫声');
end;
procedure TDog.Cry;
begin
WriteLn('汪汪汪');
end;
var
Pet: TAnimal;
begin
// 父类实例
Pet := TAnimal.Create;
try
Pet.Cry;
finally
FreeAndNil(Pet);
end;
// 子类实例,父类变量接收,多态生效
Pet := TDog.Create;
try
Pet.Cry;
finally
FreeAndNil(Pet);
end;
end.Code language: JavaScript (javascript)
执行结果
D:\fpcdemo>fpc mydemo.dpr
Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling mydemo.dpr
Linking mydemo.exe
45 lines compiled, 0.1 sec, 68544 bytes code, 4260 bytes data
D:\fpcdemo>mydemo
动物发出叫声
汪汪汪Code language: CSS (css)
FreeAndNil
安全释放对象,两步合一:
- 调用对象
Free销毁内存; - 把变量置为
nil,防止野指针。

上面这句代码是一个子类的TDog对象存储在TAnimal Pet的变量里面,但是下面用Pet去调用Cry的时候,指向的是TDog里面的Cry,不是TAnimal里面的Cry,这里就是多态。
Cry; virtual父类标记为虚方法,开启运行时多态;- 子类用
override重写Cry; - 变量声明是
TAnimal,但实际对象是TDog,自动执行狗的叫声。
标记 virtual 的方法:编译器运行时根据对象实际类型匹配对应方法实现。
如果删掉 virtual、override
两次调用都会执行父类方法

上面是删除了virtual、override

输出的都是TAnimal中的
编译器只认变量声明类型 TMyClass,无视对象实际类型。
- 普通方法默认非虚,加
virtual才是虚方法; - 子类重写父类虚方法必须写
override,否则编译器警告; - 若想屏蔽父类同名虚方法、不做重写,使用
reintroduce(不推荐,易造成混淆)相当于 C#中的new