Насколько совместимы статические методы классов и обычные рутинные указатели?

Мне кажется, что методы статического класса и обычные указатели на рутину совместимы с практической точки зрения, но компилятор этого не знает. Пример:

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 оба компилируются (где компиляция включает работы во время выполнения в этом простом примере). 2a и 2b оба компилируются тогда и только тогда, когда $TYPEDADDRESS является OFF, Но 1a/1b отличаются: 1b всегда компилируется, а 1a никогда не компилируется. Это различие по дизайну? Используете ли вы 3a save или я пропустил какие-либо подводные камни?

1 ответ

Решение

На двоичном уровне нет никакой разницы между статической функцией класса и обычной функцией с одинаковыми аргументами и типом результата - они двоично совместимы, поэтому ваш пример в порядке. Конечно, это разные типы для компилятора, поэтому вам нужно Addr() или же @ составить ваш пример.

Addr() эквивалентно @ оператор, за исключением того, что он не зависит от директивы компилятора $T. Если вы переключите проверку типа в вашем примере, вы не скомпилируете:

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

[Ошибка Паскаля] Project10.dpr(28): E2010 Несовместимые типы: 'TFunc' и 'Pointer'

Другие вопросы по тегам