delphi – 静态类方法和常规例程指针的兼容性如何?

在我看来,静态类方法和常规例程指针从实际角度兼容,但编译器不知道这一点.例:

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保存还是我忽略了任何陷阱?

解决方法

静态类函数和具有相同参数和结果类型的普通函数之间的二进制级别没有区别 – 它们是二进制兼容的,因此您的示例是可以的.当然它们是编译器的不同类型,因此您需要Addr()或@来编译您的示例.

Addr()等同于@运算符,除了它不受$T编译器指令的影响.如果你切换类型检查你的例子将无法编译:

{$T+}
begin
  CallIt(@TMyClass.StaticMethod);
  Readln;
end.

[Pascal Error] Project10.dpr(28):E2010不兼容的类型:’TFunc’和’Pointer’

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...