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

发布于 2024-11-27 21:35:28 字数 1088 浏览 1 评论 0原文

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

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 都可以编译(其中编译包括在这个简单示例中在运行时工作)。当且仅当 $TYPEDADDRESSOFF 时,2a 和 2b 才会编译。但 1a/1b 是不同的:1b 总是编译,而 1a 从不编译。这是设计上的区别吗?使用 3a 保存还是我忽略了任何陷阱?

It seems to me that static class methods and regular routine pointers are compatible from a practical viewpoint but the compiler doesn't know this. Example:

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.

As noted in the comments, 3a and 3b both compile (where compiles includes works at runtime in this simple example). 2a and 2b both compile if and only if $TYPEDADDRESS is OFF. But 1a/1b are different: 1b always compiles while 1a never compiles. Is this distinction by design? Is using 3a save or have I overlooked any pitfalls?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

孤独陪着我 2024-12-04 21:35:28

具有相同参数和结果类型的静态类函数和普通函数在二进制级别上没有区别 - 它们是二进制兼容的,所以你的例子没问题。当然,对于编译器来说它们是不同的类型,因此您需要 Addr()@ 来编译您的示例。

Addr() 等同于 @ 运算符,只不过它不受 $T 编译器指令的影响。如果您切换示例上的类型检查,则不会编译:

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

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

There is no difference on binary level between static class function and ordinary function with the same arguments&result type - they are binary compatible, so your example is OK. Of course they are different types for the compiler, so you need Addr() or @ to compile your example.

Addr() is equivalent to the @ operator except that it is unaffected by the $T compiler directive.If you switch type check on your example will not compile:

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

[Pascal Error] Project10.dpr(28): E2010 Incompatible types: 'TFunc' and 'Pointer'

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文