静态类方法和常规例程指针的兼容性如何? [英] How compatible are static class methods and regular routine pointers?
问题描述
在我看来,从实际的角度来看,静态类方法和常规例程指针是兼容的,但是编译器不知道这一点。示例:
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.
如注释中所述,3a和3b都可以编译(其中 compile 在这个简单的示例中包括在运行时有效)。 2a和2b都在且仅当 $ TYPEDADDRESS
为 OFF
时才编译。但是1a / 1b有所不同:1b始终编译,而1a从未编译。这是设计上的区别吗?正在使用3a保存还是忽略了任何陷阱?
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?
推荐答案
静态类函数和普通函数在二进制级别上没有区别具有相同的参数和结果类型-它们是 binary 兼容的,因此您的示例很好。当然,对于编译器而言,它们是不同的类型,因此您需要 Addr()
或 @
来编译示例。
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()
等效于 @
运算符,除了则不受$ T编译器指令的影响。如果切换类型检查,则示例将无法编译:
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不兼容的类型:'TFunc'和'Pointer '
[Pascal Error] Project10.dpr(28): E2010 Incompatible types: 'TFunc' and 'Pointer'
这篇关于静态类方法和常规例程指针的兼容性如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!