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

您正在尝试比较三个完全不同的实体。

@test 返回变量 test 的地址,而不是它指向的对象实例。

test.getClassPointer() 返回类元数据的地址,编译器生成的常量数据结构,运行时可以在其中找到虚拟方法表、运行时类型信息表等。一个类的所有实例共享相同的类元数据结构。指向类元数据的指针是对象实例的类型标识——它是对象在运行时知道它是什么类型的方式。

test.getSelfPointer() 为您提供对象实例在内存中的实际地址。两个对象实例(单独创建)将具有不同的实例地址。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已经引用的对象实例进行第二次引用,请编写:

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 回答