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 のエラーが発生します - 定数式が必要です。これらは、クラスの 2 つのメソッドです。これを機能させるために使用する必要がある構文はありますか、それとも実行時に配列を構築するのに行き詰まっていますか?

4

2 に答える 2

7

オブジェクトのメソッドは、2 ポインター型として知られているものです。次の情報をカプセル化します。

  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)
  );

fn次に、 ofを呼び出す必要がある場合(メソッドとメソッドcmds[i]を定義する同じクラス内で呼び出しが行われると思います)、次のように記述します。DoHelpDoLoad

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