delphi - Delphi-维护对对象的 self 引用

标签 delphi pointers self

我看过许多与对象中的“ Self”变量有关的问题和资源,但是每个人的说法都不尽相同。

例如,在以下问题中:Delphi Self-Pointer usage

该问题的最高评分答案似乎是错误的。 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
  .
  .
  .


在大多数情况下,这种方法效果很好。

我的问题是:这是一种好的编码习惯吗?在程序执行期间,“ PSelf”变量是否可以指向该对象?

最近,我遇到了一个错误,其中“ PSelf”已停止指向它包含的对象,并且我想知道对象是否曾经在堆中乱堆,或者内存是否已损坏。

编辑:

在某些情况下,使用“ Self”变量对我不起作用,现在我无法复制它。因此,整个问题毫无意义,就像我使用“ PSelf”变量的技术一样。对于那个很抱歉。

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

最佳答案

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

包含类实例的变量已经是指向该对象实例的指针。为了方便起见,Delphi编译器仅允许您省去解引用运算符(^)。

var
  MyObject: TMyObject;  
begin
  MyObject := TMyObject.Create;  // MyObject is now a pointer to an instance of TMyObject
  ...


当访问对象实例的成员或属性时,Delphi还允许不使用解引用运算符的快捷方式。同样,以下代码实际上是等效的:

MyObj.SomeProperty := SomeValue;
MyObj^.SomeProperty := SomeValue;


Delphi documentation


类类型的变量实际上是引用对象的指针。因此,一个以上的变量可以引用同一对象。与其他指针一样,类类型变量可以保留值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;        


请注意,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`

关于delphi - Delphi-维护对对象的 self 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14027244/

相关文章:

python - 是否可以在不定义类的情况下编写一个以 "self"作为参数的函数?

python - python中的类实例化和 'self'

delphi - 最小化 Firemonkey 应用程序中的表单

delphi - SocketStream发送十六进制值

delphi - IPPeerCommon 和 IPPeerClient

c - 在数组中找到孤独的整数

c - 解决底层管理功能UD的建议

ruby - 使用 class << self,什么时候使用类或模块?

delphi - 在 Delphi 中,如何检查 IInterface 引用是否实现派生但未显式支持的接口(interface)?

c++ - 指针与引用