Следующий код даст вам объяснение:
type
TA = class( TInterfacedObject)
public
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
end;
procedure TA.AfterConstruction;
begin
inherited;
writeln('AfterConstruction=',integer(self));
writeln('AfterConstruction=',integer(addr(self)));
end;
procedure TA.BeforeDestruction;
begin
writeln('BeforeDestruction=',integer(self));
writeln('BeforeDestruction=',integer(addr(self)));
inherited;
end;
Вот вывод:
AfterConstruction=10731904
AfterConstruction=1245020
BeforeDestruction=10731904
BeforeDestruction=1245028
Таким образом, целое число (self) является правильным (оба значения равны 10731904), а целое число (addr (self)) - нет.
Потому что addr (self) показывает не значение self, а место хранения значения self.
В обоих случаях он хранится в стеке (используйте Alt-F2, чтобы разобрать префикс обоих методов):
mov [esp],eax
Поэтому, когда вы используете addr (self), вы смотрите на текущий адрес стека, а не на значение self.
Addr - это не просто приведение типа к указателю, но то же самое, что и @self, поэтому использование integer (self) не совпадает с integer (addr (self)).
Вы не должны использовать Addr (self), но self, чтобы найти адрес выделения вашего объекта.