2017-02-07 7 views
5

私は自己についての理解を進めることを求めています。自己の範囲は何ですか?

次の点を考慮してください:

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イベント(ButtonSecondClick)でMakeThePointerを呼び出すと、正常に動作します。ポインタ(ButtonThirdClick)にアクセスする前にMakeThePointerに電話しないと、以前に作成されたポインタが有効でアクセス違反が発生するような方法でTestObj's 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; 

答えて

4

自己のスコープとは何ですか?

Selfは、ローカル変数として最もよく考えられます。したがって、そのアドレス、@Selfは、メソッドが戻るまで有効です。

これは、コードが失敗する理由を説明しています。メソッドが返された後、コードがポインタを逆参照します。ポインタが無効なポイントです。

私は、Self変数が常に同じアドレスにあると想定していますか?

いいえ、そうでないかもしれません。


私はあなたの問題はここからだと思う:

type 
    PTestObject = ^TTestObject; 

TTestObjectがクラスであるので、そのようなあなたのSelfなど種類TTestObjectの変数は、参照です。参照は、ポインタの空想的な名前です。この場合、Selfの内部メソッドTTestObjectはインスタンスへのポインタです。

^TTestObjectの代わりにTTestObjectを使用してください。問題は解消されます。

関連する問題