Использование Delphi Self-Pointer - PullRequest
       7

Использование Delphi Self-Pointer

5 голосов
/ 29 сентября 2010

Мне нужно получить указатель на мой экземпляр класса внутри этого экземпляра.Я не могу использовать "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» указателем на этот экземпляр класса?Как использовать этот указатель для будущего использования вне этого объекта?Как получить правильный указатель из этого значения?

Ответы [ 2 ]

12 голосов
/ 29 сентября 2010

Вы пытаетесь сравнить три совершенно разные сущности.

@ 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.
0 голосов
/ 29 сентября 2010

В вашем фрагменте кода 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;
...