8

同じフィールドを持つ 2 つのレコードがあり、そのうちの 1 つには一連の手順があります。両方のレコードのサイズが同じなのはなぜですか?

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TData = record
    Age : Byte;
    Id  : Integer;
  end;

  TData2 = record
    Age : Byte;
    Id  : Integer;
    procedure foo1;
    procedure foo2;
    procedure foo3;
  end;

procedure TData2.foo1;
begin

end;

procedure TData2.foo2;
begin

end;

procedure TData2.foo3;
begin

end;

begin
  try
    Writeln('SizeOf(TData) = '+ IntToStr(SizeOf(TData)));
    Writeln('SizeOf(TData2) = '+ IntToStr(SizeOf(TData2)));
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.
4

2 に答える 2

10

これは、レコード自体がレコードを構成するデータのみを保持し、手順や機能がないためです。プロシージャと関数は、レコード自体をパラメーターとして渡すことを避けるための一種の構文糖衣です。つまり、コンパイラーによって自動的に追加されるself変数です。

レコードで宣言する各メソッドには、レコード自体の別のパラメーターがあります。次に例を示します。

  TData2 = record
    Age : Byte;
    Id  : Integer;
    procedure Foo1;
    procedure Foo2(SomeParam: Integer);
  end;

次と同等のものに変更されます。

  PData2 = ^TData2;

  TData2 = record
    Age : Byte;
    Id  : Integer;
  end;

  procedure TData2_Foo1(Self: PData2);
  procedure TData2_Foo2(Self: PData2; SomeParam: Integer);

end 各呼び出しも変更されます。たとえば、次のようになります。

var
  Data: TData2;
begin
  Data.Foo1;
  Data.Foo2(1);
end;

は次と同等のものに変更されます。

var
  Data: TData2;
begin
  TData2_Foo1(@Data);
  TData2_Foo1(@Data, 1);
end;

パラメータがパラメータ リストの先頭または末尾に追加されているかどうかを確認する Delphi は手元にありませんが、理解していただければ幸いです。

もちろん、これには実際の構文はありません。これは、コンパイラによってオンザフライで行われるため、たとえば、プロシージャ名は変更されないためです。私は自分の答えを理解しやすくするためにそうしました。

于 2013-01-16T03:04:58.703 に答える
0

手続きは場所を取らない。コンパイラはそれらを適切に接続します。それらのアドレスは、各レコードの実行時にメモリ内にある必要はありません。メモリ内の TData2 の表現を見ると、プロシージャが見つかりません。

于 2013-01-16T03:03:37.240 に答える