考虑以下 Delphi 控制台应用程序:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TC1 = class
procedure m; virtual;
end;
TC2 = class(TC1)
procedure m; override;
end;
type THelper = class helper for TC1
procedure m;
end;
procedure TC1.m; begin WriteLn('C1') end;
procedure TC2.m; begin WriteLn('C2') end;
procedure THelper.m; begin inherited m end;
procedure p(c : TC1);
begin
C.m
end;
begin
var C := TC2.Create;
p(c);
ReadLn
end.
我希望THelper
的存在不会改变继承并打印“C2”,但程序会打印“C1”,因此不会调用重写的C2.m
。
当注解掉THelper
(和THelper.m
)时,程序按预期打印“C2”。
1条答案
按热度按时间ghg1uchk1#
在本例中,
THelper.m()
优先于TC1.m()
。这是预期和记录的行为:Class and Record Helpers (Delphi)
下面的代码演示了类助手的声明(记录助手的行为方式相同):
提示:记住,类助手函数
MyFunc
被调用,因为类助手优先于实际的类类型。最后强调的部分是为什么
p()
调用THelper.m()
而不是TC1.m()
。由于
THelper.m()
正在调用inherited m()
,这是对TC1.m()
的直接调用,因此不会发生虚拟方法分派,这就是为什么TC2.m()
根本不会被调用,即使p()
的c
参数指向TC2
对象。如果让
THelper.m()
调用Self.m()
而不是inherited m()
,这将允许编译器调用TC1.m()
上的虚方法分派,从而调用TC2.m()
,因为THelper
内部的Self
指针引用TC1
,而不是THelper
。