在我看来,静态类方法和常规例程指针从实际角度兼容,但编译器不知道这一点。例如:
type
TFunc = function(i: Integer): string;
TMyClass = class
public
class function StaticMethod(i: Integer): string; static;
end;
class function TMyClass.StaticMethod(i: Integer): string;
begin
Result := '>' + IntToStr(i) + '<';
end;
function GlobalFunc(i: Integer): string;
begin
Result := '{' + IntToStr(i) + '}';
end;
procedure CallIt(func: TFunc);
begin
Writeln(func(42));
end;
begin
CallIt(TMyClass.StaticMethod); // 1a: doesn't compile
CallIt(GlobalFunc); // 1b: compiles
CallIt(@TMyClass.StaticMethod); // 2a: compiles iff $TYPEDADDRESS OFF
CallIt(@GlobalFunc); // 2b: compiles iff $TYPEDADDRESS OFF
CallIt(Addr(TMyClass.StaticMethod)); // 3a: compiles
CallIt(Addr(GlobalFunc)); // 3b: compiles
Readln;
end.
如评论中所述,3a和3b都编译(其中编译包括在运行时在这个简单的例子中工作)。当且仅当$TYPEDADDRESS
为OFF
时,2a和2b都编译。但是1a / 1b是不同的:1b总是编译而1a从不编译。这是设计上的区别吗?使用3a保存还是我忽略了任何陷阱?
答案 0 :(得分:7)
静态类函数和具有相同参数和结果类型的普通函数之间的二进制级别没有区别 - 它们与二进制兼容,因此您的示例是正常的。当然它们是编译器的不同类型,因此您需要Addr()
或@
来编译您的示例。
Addr()
等同于@
运算符,除了它不受$ T编译器指令的影响。如果切换类型检查,您的示例将无法编译:
{$T+}
begin
CallIt(@TMyClass.StaticMethod);
Readln;
end.
[Pascal Error] Project10.dpr(28):E2010不兼容的类型:'TFunc'和'Pointer'