是否可以初始化函数引用的常量数组?

时间:2018-06-27 09:43:58

标签: delphi delphi-10.1-berlin

在此之后,在阅读关于procedural typesanonymous methodsDavid Heffernan's explanation的Embarcadero文档之后,我还是不太明白为什么编译器禁止初始化对函数的常量引用数组,例如在下面的示例中为C_BAR。

program MyProgram;

{$APPTYPE CONSOLE}

{$R *.res}

type
  TFoo = function: Integer;
  TBar = reference to function: Integer;

  function FooBar: Integer;
  begin
    Result := 42;
  end;

const
  // This works
  C_FOO: array[0..0] of TFoo = (FooBar);

  // These lines do not compile
  // C_BAR: array[0..0] of TBar = (FooBar); // TBar incompatible with Integer
  // C_BAR: array[0..0] of TBar = (@FooBar); // TBar incompatible with Pointer

var
  Foo: array[0..0] of TFoo;
  Bar: array[0..0] of TBar;
begin
  Foo[0] := FooBar; // Foo[0] = MyProgram.FooBar
  Bar[0] := FooBar; // Bar[0] = MyProgram$1$ActRec($1CC8CF0) as TBar

  Foo[0] := C_FOO[0]; // Foo[0] = MyProgram.FooBar
  Bar[0] := C_FOO[0]; // Bar[0] = MyProgram$1$ActRec($1CC8CF0) as TBar
end.

使用调试器,我可以看到Bar [0]等于某个地址(我认为吗?),这表明我的理解背后正在发生某些事情……

那么在我的示例中是否可以初始化诸如C_BAR的常量数组?如果是,该怎么做,否则,为什么?

1 个答案:

答案 0 :(得分:7)

相关文档在Typed Constants的部分中:

  

类型化常量与真实常量不同,可以保存数组的值,   记录,过程和指针类型。类型常量不能出现在   常量表达式。

     

声明这样的类型常量:

const identifier: type = value
     

其中,标识符是任何有效标识符,类型是除以下类型之外的任何类型   文件和变体,值是类型的表达。例如,

const Max: Integer = 100;
     

在大多数情况下,value必须是一个常量表达式;但是如果type是一个   数组,记录,过程或指针类型,需要应用特殊规则。

这些用于程序类型的特殊规则如下:

  

要声明过程常量,请指定函数名称或   与常量的声明类型兼容的过程。   例如,

function Calc(X, Y: Integer): Integer;
begin
  ...
end;
type TFunction = function(X, Y: Integer): Integer;
const MyFunction: TFunction = Calc;
     

鉴于这些声明,您可以使用过程常量   函数中的MyFunction:

I := MyFunction(5, 7)
     

您还可以将值nil分配给过程常量。

所以这解释了为什么可以使用TFoo声明类型化的常量。

至于匿名方法,本文档未在任何地方列出它们。现在,匿名方法被实现为接口。该接口具有由编译器生成的后备类,因此需要创建该类的实例。该实例是在堆上分配的,这是(至少一个原因)为什么您不能将匿名方法声明为常量。