自我的范围是什么?

时间:2017-02-07 08:53:30

标签: delphi

我要求提升我对自我的理解。

请考虑以下事项:

type
  PTestObject = ^TTestObject;
  TTestObject = class(TObject)
  private
    FCaption : String;
  public
    procedure MakeThePointer;

    property Caption : String read FCaption write FCaption;
  end;

  TForm4 = class(TForm)
    ButtonFirst: TButton;
    ButtonSecond: TButton;
    ButtonThird: TButton;
    procedure ButtonFirstClick(Sender: TObject);
    procedure ButtonSecondClick(Sender: TObject);
    procedure ButtonThirdClick(Sender: TObject);
  private
  public
  end;

var
  Form4: TForm4;
  PointerOfTest : PTestObject;
  TestObj : TTestObject;

implementation

{$R *.dfm}

procedure TTestObject.MakeThePointer;
begin
  PointerOfTest := @Self;
end;

procedure TForm4.ButtonFirstClick(Sender: TObject);
begin
  TestObj := TTestObject.Create;
  TestObj.Caption := 'Hello';
  TestObj.MakeThePointer;
end;

procedure TForm4.ButtonSecondClick(Sender: TObject);
begin
  TestObj.MakeThePointer;
  ShowMessage(PointerOfTest^.Caption);
end;

procedure TForm4.ButtonThirdClick(Sender: TObject);
begin
  // TestObj.MakeThePointer; - Because I do not do this I get Access Violation
  ShowMessage(PointerOfTest^.Caption);
end;

我的想法是创建一个指向TestObj's Self的指针,然后再次访问它。如果我在同一个Click事件(MakeThePointer)中调用ButtonSecondClick,我可以访问该指针,它可以正常工作。如果我在访问指针(MakeThePointer)之前没有调用ButtonThirdClick,那么似乎TestObj's Self不存在以前创建的指针有效并且我得到访问冲突。

如果我错了,请纠正我,但我认为Self是每个对象方法的局部变量。因此,它将仅分别针对每种方法的范围?

现在考虑一下......如果是这种情况,那么为什么如果单击ButtonFirst,则下面的工作会起作用,然后是ButtonSecond?似乎Self变量已落在同一地址上,因此允许以下工作。我可以假设Self变量将始终位于同一地址或将更改吗?

type
  TFormOther = class(TForm)
    ButtonFirst: TButton;
    ButtonSecond: TButton;
    procedure ButtonFirstClick(Sender: TObject);
    procedure ButtonSecondClick(Sender: TObject);
  private
  public
    procedure MakeThePointer;
    procedure SetTheCaption;
  end;

var
  FormOther: TFormOther;
  PointerOfForm : ^TForm;

implementation

{$R *.dfm}

procedure TFormOther.MakeThePointer;
begin
  PointerOfForm := @Self;
end;

procedure TFormOther.SetTheCaption;
begin
  PointerOfForm^.Caption := 'Hello';
end;

procedure TFormOther.ButtonFirstClick(Sender: TObject);
begin
  MakeThePointer;
end;

procedure TFormOther.ButtonSecondClick(Sender: TObject);
begin
  SetTheCaption;
end;

1 个答案:

答案 0 :(得分:4)

  

Self的范围是什么?

在方法Self中,最好将其视为局部变量。因此,它的地址@Self在方法返回之前是有效的。

这解释了您的代码失败的原因。您的代码在方法返回后取消引用指针,此时指针无效。

  

我可以假设Self变量将始终位于同一地址吗?

不,你可能没有。

我认为你的问题从这里开始:

type
  PTestObject = ^TTestObject;

由于TTestObject是一个类,因此TTestObject类型的变量(例如Self)是一个参考。引用是指针的奇特名称。在这种情况下,Self的{​​{1}}内部方法是指向实例的指针。

因此请使用TTestObject代替TTestObject,并解决您的问题。