@Object和Pointer(Object)有什么区别?

时间:2018-07-07 08:01:55

标签: delphi

我正在测试以下代码:

type
  TPersonA = class
    public
      procedure Speak;virtual;
  end;

  TPersonB = class
    public
      procedure Speak;virtual;
  end;
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var PersonA: TPersonA;
    PersonB : TPersonB;
begin
  PersonA := TPersonA.Create;
  PersonB := TPersonB.Create;

  PersonA := Pointer( PersonB );
  PersonA.Speak;
end;

procedure TPersonA.Speak;
begin
  ShowMessage('Hello');
end;


procedure TPersonB.Speak;
begin
  ShowMessage('Hello again');
end;

end.

因此,如果我使用虚拟方法运行此代码,并将PersonB的指针传递给PersonA并调用Speak,则会执行PersonB.Speak。

但是,如果我在这两个方法中都删除了虚拟指令,然后再次运行,则delphi将PersonA的方法作为静态方法执行,因为它的地址将被直接编译到调用位置的代码中。

因此,当两个方法都声明为虚拟方法时,我更改了代码:

PersonA:=指针(PersonB)==> PersonA:= @PersonB

我遇到了访问冲突。我想在第一种情况下是在使用指针指针,但是在那种情况下我对@的用法感到困惑。

3 个答案:

答案 0 :(得分:6)

类型源自TObject的变量实际上是指向实例的指针。

所以Pointer(PersonB)也是实例的指针。但是@ObjectB是指向实例的指针的地址。那是间接的一个额外层次。

FWIW这两个选项都是没有意义的,不会导致有用的地方。

对于删除virtual指令时的不同行为,使用实例的运行时类型调度虚拟方法,使用实例变量的编译时类型调度非虚拟方法。代码完全运行的事实是由于两个不相关的类具有兼容的VMT。但这只是实现细节的机会。

答案 1 :(得分:6)

让我们做一个简单的图(组成地址):

Address                        Value
          +-----------------+
12345600  |  Obj variable   |  45680000
          +-----------------+
                   |
                   v
          +-----------------+
45680000  |     instance    |  
          |                 |
          |                 |
          +-----------------+

Obj是一个变量。它是一个对象引用,这意味着它实际上是指向实例的指针。

如果采用@Obj,则采用变量的地址。其类型为Pointer

  

因此您得到@Obj = Pointer($12345600)

如果将Obj强制转换为PointerPointer(Obj),您将获得变量指向的实例地址。它的类型也是Pointer

  

因此您得到Pointer(Obj) = Pointer($45680000)

您甚至可以对此进行测试:

if @Obj = Obj then
  Writeln('Same')
else
  Writeln('Different');
if Pointer(Obj) = Obj then
  Writeln('Same')
else
  Writeln('Different');

您应该得到:

Different
Same

编辑

我将Object更改为Obj,因为在Delphi中object是保留字。


我在指针上的文章中的更多信息:Addressing pointers

答案 2 :(得分:0)

Pointer(Object)是强制类型转换,@Object是对象的地址。换句话说@Object <> Pointer(Object)。使用Pointer(Object)时,您没有获得指向Object的指针,而获得了原始指针的值。