6

このインスタンス内のクラス インスタンスへのポインターを取得する必要があります。「Self」を直接使用することはできません。将来の使用のためにストア ポインターが必要です。次のコードを試しました:

type
    TTest = class(TObject)
    public
        class function getClassPointer: Pointer;
        function getSelfPointer: Pointer;
    end;

class function TTest.getClassPointer: Pointer;
begin
    Result := Pointer(Self);
end;

function TTest.getSelfPointer: Pointer;
begin
    Result := Pointer(Self);
end;

そして両方の結果が間違っています - このコード:

test := TTest.Create;
Writeln('Actual object address: ', IntToHex(Integer(@test), 8));
Writeln('Class "Self" value: ', IntToHex(Integer(test.getClassPointer()), 8));
Writeln('Object "Self" value: ', IntToHex(Integer(test.getSelfPointer()), 8));

戻り値:

Actual object address:    00416E6C
Class "Self" value:       0040E55C
Object "Self" value:      01EE0D10

この「自己」値とは何ですか?「Self」はこのクラス インスタンスへのポインタですか? このオブジェクトの外で将来使用するために、このポインターをどのように使用しますか? この値から適切なポインタを取得するにはどうすればよいですか?

4

2 に答える 2

13

3 つの完全に異なるエンティティを比較しようとしています。

@test は、それが指すオブジェクト インスタンスではなく、変数 test のアドレスを返します。

test.getClassPointer() は、クラス メタデータのアドレス、ランタイムが仮想メソッド テーブル、ランタイム型情報テーブルなどを見つけることができるコンパイラによって生成された定数データ構造を返します。クラスのすべてのインスタンスは、同じクラス メタデータ構造を共有します。クラス メタデータへのポインターは、オブジェクト インスタンスの型 ID です。これは、実行時にオブジェクトがどの型であるかを認識する方法です。

test.getSelfPointer() は、メモリ内のオブジェクト インスタンスの実際のアドレスを提供します。2 つのオブジェクト インスタンス (別々に作成) は、異なるインスタンス アドレスを持ちます。test.getSelfPointer() は、テスト インスタンス変数の内容と等しくなります: Pointer(test)

例(疑似コード、テストされていません):

type TTest = class
     end;

var test1: TTest;
    test2: TTest;

begin
  test1 = TTest.Create;  // allocates memory from the global heap, stores pointer
  test2 = test1;         // copies the pointer to the object into test2 variable
  writeln("Test1 variable points to: ", IntToHex(Integer(Pointer(test1))));
  writeln("Test2 variable points to: ", IntToHex(Integer(Pointer(test1))));
end.
于 2010-09-29T17:25:06.663 に答える
0

コードフラグメントtestではすでに実際のインスタンスへの参照であるため、試してみてください

Writeln('Actual object address: ', IntToHex(Integer(Pointer(test)), 8));

また、おそらく getSelfPointer メソッドは必要ありません。test既に参照しているオブジェクト インスタンスへの 2 番目の参照が必要な場合は、次のように記述します。

var
  SecondReferenceToTest: TTest;
SecondReferenceToTest := test;

これを確認するには、次のようにしてみてください。

type
  TTest = class(TObject)
  public
    Name: string;
  end;

procedure TestProc;
var
  test, SecondReferenceToTest: TTest;
begin
  test := TTest.Create;
  try
    test.Name := 'Named via "test" reference';
    SecondReferenceToTest := test;
    ShowMessage(SecondReferenceToTest.Name);
  finally
    test.Free;
  end;
end;
于 2010-09-29T17:23:21.563 に答える