我正在测试以下代码:

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。

但是,如果我删除两个方法中的 virtual 指令并再次运行,则 delphi 将 PersonA 的方法作为静态执行,因为它的地址将在调用它的地方直接编译到代码中。

所以,当这两种方法都被声明为 virtual 并且我更改了代码时:

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

我遇到了访问冲突。我认为在第一种情况下是在做一个指针指针,但在这种情况下我对 @ 的用法感到困惑。

最佳答案

类型从TObject派生的变量实际上是指向实例的指针。

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

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

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

关于delphi - @Object 与 Pointer( Object ) 有什么区别?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51221193/

10-11 18:37