8

我想在记录中使用对象过程,如下所示:

TCommandRec = record
  name: string;
  fn: procedure of object;
end;

我可以通过赋值创建一个数组:

commands: array [0..1] of TCommandRec;

...

commands[0].name := '-help';
commands[0].fn := DoHelp;
commands[1].name := '-load';
commands[1].fn := DoLoad;

我真正想做的是声明一个常量:

const
  cmds: array [0..1] of TCommandRec =
  (
    (name: '-help'; fn: DoHelp),
    (name: '-load'; fn: DoLoad)
  );

但是,我收到 DoHelp 和 DoLoad 错误 - 预期的常量表达式。这是一个类的两个方法。我需要使用一些语法来完成这项工作,还是我在运行时卡住了构建数组?

4

2 回答 2

7

对象方法是所谓的双指针类型。它封装了以下信息:

  1. 函数的地址。
  2. 对象或主题的地址。

前者在编译时是已知的,但通常后者不是。这就是为什么您通常需要在运行时创建这些东西的原因。

如果您可以安排在编译时知道主题,那么您可以声明您的记录类型的类型化常量。例如:

type
  TMyRecord = record
    Foo: procedure of object;
  end;

  TMyStaticClass = class
    class procedure Foo;
  end;

class procedure TMyStaticClass.Foo;
begin
end;

const
  MyRecord: TMyRecord = (Foo: TMyStaticClass.Foo);

当然,只有当你的函数可以作为类方法而不是实例方法时,这才会对你有用。我只是添加上面的代码来说明您可以拥有常量方法指针,只要主题是编译时常量。

于 2013-06-15T09:16:08.950 回答
2

您可以在记录中存储指向方法的指针(这些在编译时是已知的,因此在 const 定义中指定它们没有问题):

TCommandRec = record
  name: string;
  fn: Pointer;
end;

...
const
  cmds: array [0..1] of TCommandRec =
  (
    (name: '-help'; fn: @DoHelp),
    (name: '-load'; fn: @DoLoad)
  );

然后,当您需要调用fnof cmds[i](我想调用发生在定义DoHelpandDoLoad方法的同一个类中)时,编写如下内容:

type TObjectProc = procedure of object;
var m: TMethod;
...
m.Code := cmds[i].fn;
m.Data := Self;
TObjectProc(m);
于 2013-06-15T09:21:34.100 回答