Delphi - 维护对象的自引用

Aud*_*oGL 1 delphi pointers self

我已经看过很多问题和资源,它们处理对象中的"Self"变量,但每个人都说不同的东西.

例如,在这个问题中:Delphi Self-Pointer用法

该问题得分最高的答案似乎是错误的.指针(Self)不指向包含它的对象,也不能用于从对象内部传递引用.

我试过这样做:

Type
  myobject = class
    PSelf: Pointer;
  End;

Var
  Obj: myobject;

Procedure RunProgram;
Begin
  Obj := myobject.create;
  Obj.PSelf := @Obj;

  //Run the rest of the program
  .
  .
  .
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,这工作得很好.

我的问题是:这是一个很好的编码实践吗?可以期望"PSelf"变量在程序执行期间指向对象吗?

我最近遇到了一个错误,"PSelf"已经停止指向它包含对象,我想知道对象是否在堆中被拖曳,或者内存是否已损坏.

编辑:

在某些情况下,使用"Self"变量对我来说不起作用,现在我无法复制它.因此,整个问题毫无意义,我使用'PSelf'变量的技术也是如此.对于那个很抱歉.

正如Ken所指出的,上面的链接有正确的答案:)

Ken*_*ite 14

我认为你误解Self了对象是什么,以及对象引用如何在Delphi中工作.

包含类实例的变量已经是指向该对象实例的指针.Delphi编译器只允许您省略dereference运算符(^)以方便使用.

var
  MyObject: TMyObject;  
begin
  MyObject := TMyObject.Create;  // MyObject is now a pointer to an instance of TMyObject
  ...
Run Code Online (Sandbox Code Playgroud)

Delphi还允许在访问对象实例的成员或属性时不使用解引用运算符的简写.同样,以下代码实际上是等效的:

MyObj.SomeProperty := SomeValue;
MyObj^.SomeProperty := SomeValue;
Run Code Online (Sandbox Code Playgroud)

Delphi文档中:

类类型的变量实际上是引用对象的指针.因此,多个变量可以引用同一个对象.与其他指针一样,类类型变量可以保持值为nil.但是,您不必显式取消引用类型变量来访问它指向的对象.例如,SomeObject.Size:= 100将值100赋给SomeObject引用的对象的Size属性; 你不会把它写成SomeObject ^ .Size:= 100.

Self是一个自动声明的属性,指向对象的当前实例.换句话说,它在代码中自动可用,该代码实现该类以引用对象的当前实例.这允许您拥有同一对象的多个实例:

type
  TMyObject=class(TObject)
  private
    FMyInteger: Integer;
    function GetMyInteger: Integer;
    procedure SetMyInteger(Value: Integer);
  published
    property MyInteger: Integer read GetMyInteger write SetMyInteger;
  end;

...
function TMyObject.GetMyInteger: Integer;
begin
  Result := Self.FMyInteger; 

  // Self is implied, so the above line can more simply be written as
  // Result := FMyInteger;
end;

procedure TMyObject.SetMyInteger(Value: Integer);
begin
  if (Value <> Self.FMyInteger) then  // Self is again implied here
    Self.FMyInteger := Value;
end;

var
 MyObjOne, MyObjTwo: TMyObject;
 i, j: Integer;
begin
  MyObjOne := TMyObject;
  // Here, the code inside TMyObject.SetInteger that
  // uses `Self` would refer to `MyObjOne`
  MyObjOne.MyInteger := 1; 

  MyObjTwo := TMyObject;
  // Here, the code in TMyObject.SetInteger would be
  // using the memory in `MyObjTwo` when using `Self`
  MyObjTwo.MyInteger := 2; 
end;        
Run Code Online (Sandbox Code Playgroud)

请注意,Self在实现该类的代码中有效.它的问世,并在有效TMyObject.GetMyIntegerTMyObject.SetMyInteger以上(在我的例子中唯一实现的代码),并始终指向当前实例.

有没有需要跟踪的地址Self,作为对象实例变量引用 Self该对象实例的内部方法.它仅在该对象的实例内有效,并始终引用该对象实例.所以在你的代码示例中,PSelf只是浪费空间 - myobject已经包含指向自身的指针,并且该指针在以下方法中自动可用myobject:

type
  myobject = class;   // Now automatically contains a `Self` pointer
                      // available in methods of the class once an
                      // instance is created

var
  myobj: myobject;
begin
  myobj := myobject.Create;  // myobj.Self now is valid in methods of
                             // `myobject`
Run Code Online (Sandbox Code Playgroud)