Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi @Object和指针(Object)有什么区别?_Delphi - Fatal编程技术网

Delphi @Object和指针(Object)有什么区别?

Delphi @Object和指针(Object)有什么区别?,delphi,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); priv

我正在测试以下代码:

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.
因此,如果我使用virtual方法运行此代码,并将PersonB指针传递给PersonA并调用Speak,则PersonB.Speak将被执行

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

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

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


我违反了访问权限。我想在第一种情况下是指针的指针,但在这种情况下,我会混淆@的用法。

指针(对象)
是类型转换,
@Object
是对象的地址。换句话说
@Object
指针(Object)
。当您使用
指针(对象)
时,您不会得到指向对象的指针,而是得到原始指针值

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

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

FWIW这两个选项都是毫无意义的,不会带来任何有用的结果


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

让我们做一个简单的图表(地址由以下部分组成):

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

如果采用
@Obj
,则采用变量的地址。它的类型是
指针

所以你得到了
@Obj=Pointer($12345600)

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

所以你得到了
指针(Obj)=指针($45680000)

您甚至可以测试这一点:

if @Obj = Obj then
  Writeln('Same')
else
  Writeln('Different');
if Pointer(Obj) = Obj then
  Writeln('Same')
else
  Writeln('Different');
你应该得到:

Different
Same
编辑 我将
Object
更改为
Obj
,因为
Object
在Delphi中是一个保留字



有关指针的更多信息,请参阅我的文章:

否@Object是双指针,是指向对象实例的指针的地址。@David Heffernan和where在我的回答中说了相反的话:“当你使用指针(Object)时,你没有得到指向对象的指针”。那是错误的。指针(Object)是指向对象实例的指针。它是实例的地址。无论如何,这真的不清楚。当你使用object这个词时,不清楚你是指一个变量还是一个类实例的一般术语。事实上,尽管我没有投反对票,但我的第一反应与David的相似:你的措辞没有那么清楚。或者这一部分。“
@Object
正在获取对象的地址”。那是错误的。这是
对象的地址
本身就是对象的地址。祝贺达到500k代表!你离乔恩·斯基特不远!非常感谢您的解释和链接页面,这是迄今为止我看到的最完整的解释。
Different
Same