小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Delphi指針類型淺析(附件)

 quasiceo 2014-10-01
2010-04-26 18:12 448人閱讀 評(píng)論(0) 收藏 舉報(bào)

目錄(?)[+]

附件資料
*指針的使用(代碼)

示例:簡(jiǎn)單的指針應(yīng)用

代碼:

procedure TForm1.Button2Click(Sender: TObject);

var

    a: Integer;

    p: ^Integer;

begin

    with self.Memo1.Lines do

    begin

        a := 100;

        Add('數(shù)據(jù)內(nèi)容:' + inttostr(a));

        //---

        p := @a;

        Add('數(shù)據(jù)地址:' + inttostr(Integer(p)));

        //---

        Add('數(shù)據(jù)地址指向的內(nèi)容:' + inttostr(p^));

    end;

end;

 

procedure TForm1.Button2Click(Sender: TObject);

type

    PInteger = ^Integer;

    PPInteger = ^PInteger;

var

    a: Integer;

    p: PInteger;

    pp: PPInteger;

begin

    with self.Memo1.Lines do

    begin

        a := 100;

        Add('Integer數(shù)據(jù)內(nèi)容:' + inttostr(a));

        //---

        p := @a;

        Add('Integer指針內(nèi)容:' + inttostr(Integer(p)));

        Add('Integer指針指向的數(shù)據(jù):' + inttostr(p^));

        //---

        pp := @p;

        Add('PInteger指針內(nèi)容:' + inttostr(Integer(pp)));

        Add('PInteger指針指向的數(shù)據(jù):' + inttostr(Integer(pp^)));

    end;

end;

 

*指針的使用(匯編)

示例:簡(jiǎn)單的指針應(yīng)用

說(shuō)明:

對(duì)于編譯器來(lái)說(shuō),指針的類型可以用來(lái)標(biāo)明地址所指向區(qū)域的大小、所指向的類型(整型、對(duì)象、方法),以及進(jìn)行指針運(yùn)算時(shí)指針偏移的長(zhǎng)度。對(duì)于有類型指針的操作最終反映到編譯器的可執(zhí)行代碼中,如果不參考可執(zhí)行代碼,單憑一個(gè)內(nèi)存地址,我們并無(wú)法判斷地址所指向的數(shù)據(jù)類型。

代碼:

procedure TForm1.Button2Click(Sender: TObject);

var

    a:array[0..1] of Integer;

    b: Integer;

    p: ^Integer;

begin

    a[0] := 1;

    a[1] := 2;

    //---

    p := @a[0];

    b := p^;

    //---

    Inc(p);

    b := p^;

end;

匯編:

編譯器根據(jù)源代碼中聲明的變量類型分配內(nèi)存如下:

[ebp - $04]存儲(chǔ)為self,大小為4字節(jié),因?yàn)?/span>self聲明為對(duì)象指針

[ebp - $08]標(biāo)識(shí)為a[1],大小為4字節(jié),因?yàn)?/span>a[0]聲明為Integer

[ebp - $0c]標(biāo)識(shí)為a[0]

[ebp - $10]標(biāo)識(shí)為b,大小為4字節(jié),因?yàn)?/span>b聲明為Integer

[ebp - $14]標(biāo)識(shí)為p,大小為4字節(jié),因?yàn)?/span>p聲明為Integer指針

[ebp - $18]存儲(chǔ)為Sender,大小為4字節(jié),因?yàn)?/span>Sender聲明為對(duì)象指針

其中“ebp - $04為內(nèi)存地址,“[ebp - $04]”為地址所指向的數(shù)據(jù),ebp、eax32位寄存器可以用于存取一個(gè)4字節(jié)數(shù)據(jù)。

 

 

 

代碼:

procedure TForm1.Button2Click(Sender: TObject);

var

    a:array[0..1] of Byte;

    b: Byte;

    p: ^Byte;

begin

    a[0] := 1;

    a[1] := 2;

    //---

    p := @a[0];

    b := p^;

    //---

    Inc(p);

    b := p^;

end;

匯編:

編譯器根據(jù)源代碼中聲明的變量類型分配內(nèi)存如下:

[ebp - $04]存儲(chǔ)為self,大小為4字節(jié),因?yàn)?/span>self聲明為對(duì)象指針

[ebp - $05]標(biāo)識(shí)為a[1],大小為4字節(jié),因?yàn)?/span>a[0]聲明為Integer

[ebp - $06]標(biāo)識(shí)為a[0]

[ebp - $07]標(biāo)識(shí)為b,大小為4字節(jié),因?yàn)?/span>b聲明為Integer

[ebp - $0c]標(biāo)識(shí)為p,大小為4字節(jié),因?yàn)?/span>p聲明為Integer指針

[ebp - $10]存儲(chǔ)為Sender,大小為4字節(jié),因?yàn)?/span>Sender聲明為對(duì)象指針

其中編譯器為了實(shí)現(xiàn)數(shù)據(jù)對(duì)齊,所以申請(qǐng)了大小為$10的空間。

 

 

*復(fù)雜數(shù)據(jù)類型指針(代碼)

示例:字符串指針

代碼:

procedure TForm1.Button2Click(Sender: TObject);

type

    buffer = string[255];

    ptr = ^buffer;

var

    b1: buffer;

    b2: ptr;

begin

    with self.Memo1.Lines do

    begin

        b1 := 'zhang';

        Add('數(shù)據(jù)內(nèi)存大小:' + IntToStr(SizeOf(b1)));

        Add('數(shù)據(jù)內(nèi)容大?。?/span>' + IntToStr(PByte(@b1)^));

        //---

        b2 := @b1;

        Add('指針大小:' + IntToStr(SizeOf(b2)));

        Add('指針指向數(shù)據(jù)內(nèi)存大?。?/span>' + IntToStr(SizeOf(b2^)));

    end;

end;

說(shuō)明:

首先,ptr是一個(gè)指針類型,而b2是這個(gè)指針類型的變量。

其次,ptr是一個(gè)指向255長(zhǎng)度的短字符串類型的指針,加上一個(gè)看不見(jiàn)的計(jì)數(shù)字節(jié),共256B。當(dāng)ptr沒(méi)有分配內(nèi)存空間,也沒(méi)初始化時(shí)指向的地址是隨機(jī)的,隨意引用可能會(huì)出問(wèn)題。但是只要它指向了某個(gè)地址,就代表它指向了256B的空間,它可以指向任何有效的字符串變量,但是無(wú)論被指向的字符串有多長(zhǎng),b2^的長(zhǎng)度始終是256。

 

*記錄指針(代碼)

示例:記錄指針的應(yīng)用

代碼:

procedure TForm1.Button2Click(Sender: TObject);

type

    PTMyRecord = ^TMyRecord;

    TMyRecord = record

        Data1:Integer;

        Data2:Integer;

    end;

var

    ARecord: TMyRecord;

    pRecord: PTMyRecord;

begin

    pRecord := @ARecord;

    ARecord.Data1 := 11;

    pRecord^.Data2 := 22;

    pRecord.Data2 := 33;

end;

 

*過(guò)程指針(代碼)

示例:方法指針的結(jié)構(gòu)

說(shuō)明:

1)、過(guò)程/函數(shù)指針是一個(gè)32位的指針。

代碼:

procedure TForm1.Button2Click(Sender: TObject);

type

    TMyMethod = function(X: Integer): Integer;

var

    F: TMyMethod;

begin

    Self.Memo1.Lines.Add('函數(shù)指針大小:' + IntToStr(SizeOf(TMyMethod)));

end;

 

示例:過(guò)程指針的應(yīng)用

說(shuō)明:

1)、通過(guò)賦值語(yǔ)句“過(guò)程變量 := 過(guò)程”,使得過(guò)程變量指向過(guò)程或者函數(shù)入口地址。

2)、在賦值語(yǔ)句“過(guò)程變量 := 過(guò)程”中,左邊變量的類型決定了右邊的過(guò)程或者方法指針解釋。

3)、可以使用過(guò)程變量引用聲明的過(guò)程或者函數(shù)。

4)、無(wú)論何時(shí)一個(gè)過(guò)程變量(procedural variable)出現(xiàn)在一個(gè)表達(dá)式中,它表示調(diào)用所指向的函數(shù)或者過(guò)程。

5)、對(duì)于過(guò)程變量P, @PP轉(zhuǎn)換成一個(gè)包含地址的無(wú)類型的指針變量(即@P等價(jià)于無(wú)類型指針P),此時(shí)可以把一個(gè)無(wú)類型的指針值賦給過(guò)程變量P。

代碼:

function SomeFunction(X: Integer): Integer;

begin

    ShowMessage(IntToStr(X));

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    F: function(X: Integer): Integer;

    I: Integer;

begin

    F := SomeFunction; //--f賦值

    I := F(4);         //--調(diào)用所指向的函數(shù)

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    F: function(X: Integer): Integer;

    I: Integer;

begin

    F := SomeFunction; //--f賦值

    I := F(4); //--調(diào)用所指向的函數(shù)

    //---

    Self.Memo1.Lines.Add('函數(shù)指針大小' + IntToStr(SizeOf(@SomeFunction)));

end;

 

示例:過(guò)程指針的應(yīng)用

代碼:

function SomeFunction: Integer;

begin

    Result := 0;

    ShowMessage('0');

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    F: function: Integer;

    P:Pointer;

begin

    P := @SomeFunction; //--P賦值

    @F := P; //--f賦值

    F;

end;

說(shuō)明:

可以使用@操作符,把一個(gè)無(wú)類型的指針值賦給一個(gè)過(guò)程變量,如調(diào)用“@過(guò)程變量 := 無(wú)類型指針值”,此時(shí)過(guò)程變量指向這個(gè)值。

 

示例:過(guò)程指針的應(yīng)用

代碼:

function SomeFunction: Integer;

begin

    Result := 0;

    ShowMessage('0');

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    F,G: function: Integer;

    I: Integer;

begin

    F := SomeFunction; //--F賦值

    G := F; //--F的值拷貝給G

    I := G; //--調(diào)用函數(shù)

end;

說(shuō)明:

第一句獲得函數(shù)的入口,第二句將指針復(fù)制,第三句獲得函數(shù)的返回值。 

 

示例:過(guò)程指針的函數(shù)調(diào)用

代碼:

function SomeFunction: Integer;

begin

    Result := 0;

end;

 

function MyFunction: Integer;

begin

    Result := 0;

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    F: function: Integer;

    I: Integer;

begin

    F := SomeFunction; //--f賦值

    if F = MyFunction then

        ShowMessage('比較的函數(shù)返回值得結(jié)果');

end;

說(shuō)明:

   if語(yǔ)句中,F的出現(xiàn)導(dǎo)致一個(gè)函數(shù)調(diào)用;編譯器調(diào)用F指向的函數(shù),然后調(diào)用Myfunction,比較結(jié)果。這個(gè)規(guī)則是無(wú)論何時(shí)一個(gè)過(guò)程變量出現(xiàn)在一個(gè)表達(dá)式中,它表示調(diào)用所指向的函數(shù)或者過(guò)程。有時(shí)F指向一個(gè)過(guò)程(沒(méi)有返回值),或者f指向一個(gè)需要參數(shù)的函數(shù),則前面的語(yǔ)句會(huì)產(chǎn)生一個(gè)編譯錯(cuò)誤。

 

示例:比較過(guò)程入口地址

代碼:

function SomeFunction: Integer;

begin

    Result := 0;

end;

 

function MyFunction: Integer;

begin

    Result := 0;

    ShowMessage('123');

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    F: function: Integer;

begin

    F := MyFunction; //--f賦值

    if @F = @MyFunction then

        ShowMessage('比較函數(shù)地址');

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    F: function: Integer;

    P:Pointer;

begin

    F := MyFunction; //--f賦值

    P := @F;

    if P = @MyFunction then

        ShowMessage('比較函數(shù)地址');

end;

說(shuō)明:

@FF轉(zhuǎn)換成一個(gè)包含地址的無(wú)類型的指針變量,@myfunction返回myfunction的地址。

 

*方法指針(代碼)

示例:方法指針的結(jié)構(gòu)

說(shuō)明:

1)、方法指針指向一個(gè)結(jié)構(gòu),其結(jié)構(gòu)如下

 TMethod = record

  Code: Pointer;//指向過(guò)程/函數(shù)的指針

     Data: Pointer;//指向?qū)ο蟮闹羔?/span>

 end;

代碼:

type

    TMyObject = class(TObject)

    public

        procedure Method1(Sender: TObject);

    end;

 

procedure TMyObject.Method1(Sender: TObject);

begin

    ShowMessage('123');

end;

 

procedure TForm1.Button2Click(Sender: TObject);

type

    TMyMethod = procedure(Sender: TObject) of object;

var

    AMyMethod: TMyMethod;

    AMyObject: TMyObject;

begin

    with self.Memo1.Lines do

    begin

        Add('方法指針大?。?/span>' + IntToStr(SizeOf(TMyMethod)));

        //---

        AMyObject := TMyObject.Create;

        try

            Add('對(duì)象指針:' + IntToHex(Integer(AMyObject),2));

            Add('對(duì)象方法指針:' + IntToHex(Integer(@TMyObject.Method1),2));

            //---

            AMyMethod := AMyObject.Method1;

            //---

            with TMethod(AMyMethod) do

            begin

                Add('對(duì)象指針:' + IntToHex(Integer(Data),2));

                Add('對(duì)象方法指針:' + IntToHex(Integer(Code),2));

            end;

            //---

            AMyMethod(AMyObject);

        finally

            AMyObject.Free;

        end;

    end;

end;

 

示例:方法指針的結(jié)構(gòu)

代碼:

type

    TMyObject = class(TObject)

    public

        procedure TestMethod(Value: Integer); virtual;

    end;

    TMyObject1 = class(TMyObject)

    public

        procedure TestMethod(Value: Integer); override;

    end;

 

procedure TMyObject.TestMethod(Value: Integer);

begin

    ShowMessage('TMyObject:' + inttostr(Value));

end;

 

procedure TMyObject1.TestMethod(Value: Integer);

begin

    inherited;

    ShowMessage('TMyObject1:' + inttostr(Value));

end;

 

procedure TForm1.Button2Click(Sender: TObject);

type

    TWndMethod = procedure(Value: Integer) of object;

var

    SomeMethod: TWndMethod;

    AMyObject: TMyObject1;

    Msg: TMessage;

begin

    AMyObject := TMyObject1.Create;

    try

        SomeMethod := AMyObject.TestMethod; //--賦值后SomeMethod包含TestMethod AMyObject的指針

        //SomeMethod := TMyObject1.TestMethod;  //--錯(cuò)誤!不能用類引用。

        SomeMethod(1); //--執(zhí)行方法

    finally

        AMyObject.Free;

    end;

end;

說(shuō)明:

TWndMethod 是一種對(duì)象方法類型,它指向一個(gè)接收Integer) 類型參數(shù)的過(guò)程,但它不是一般的靜態(tài)過(guò)程,它是對(duì)象相關(guān)(object related)的。TWndMethod 在內(nèi)存中存儲(chǔ)為一個(gè)指向過(guò)程的指針和一個(gè)對(duì)象的指針,所以占用8個(gè)字節(jié)。TWndMethod類型的變量必須使用已實(shí)例化的對(duì)象來(lái)賦值。

如果把 TWndMethod變量賦值給虛方法,這時(shí),編譯器實(shí)現(xiàn)為 SomeMethod 指向AMyObject對(duì)象虛方法表中的TestMethod 過(guò)程的地址和AMyObject對(duì)象的地址。也就是說(shuō)編譯器正確地處理了虛方法的賦值。調(diào)用 SomeMethod(1) 就等于調(diào)用AMyObject.TestMethod (Message)。

在可能被賦值的情況下,對(duì)象方法最好不要設(shè)計(jì)為有返回值的函數(shù)(function),而要設(shè)計(jì)為過(guò)程(procedure)。原因很簡(jiǎn)單,把一個(gè)有返回值的對(duì)象方法賦值給TWndMethod 變量,會(huì)造成編譯時(shí)的二義性。

 

示例:方法指針指向?qū)ο蠓椒?/span>

代碼:

type

    TMyObject = class(TObject)

    public

        procedure Method1(Sender: TObject);

    end;

 

procedure TMyObject.Method1(Sender: TObject);

begin

    ShowMessage('123');

end;

 

procedure TForm1.Button2Click(Sender: TObject);

type

    TMyMethod = procedure(Sender: TObject) of object;

var

    AMyMethod: TMyMethod;

    AMyObject: TMyObject;

begin

    AMyObject := TMyObject.Create;

    try

        AMyMethod := AMyObject.Method1;

        AMyMethod(AMyObject);

    finally

        AMyObject.Free;

    end;

end;

 

示例:方法指針指向過(guò)程/函數(shù)

說(shuō)明:

1)、不能使用賦值語(yǔ)句“對(duì)象方法指針 =  @過(guò)程/函數(shù) ,因?yàn)?/span>對(duì)象方法指針和過(guò)程指針(“@過(guò)程/函數(shù)”返回一個(gè)過(guò)程指針)類型不同,它們各自的空間大小也不同,普通的過(guò)程指針不包含對(duì)象指針,所以不能用于給對(duì)象方法指針類型賦值。

2)、因?yàn)?/span>Delphi中給對(duì)象方法指針賦值必須加上對(duì)象實(shí)例,如TestObj.Hello才行,一種投機(jī)的方法是可以通過(guò)TMethod將對(duì)象方法指針重定向到一個(gè)全局函數(shù)。

3)、由于對(duì)象方法包括一個(gè)隱含對(duì)象指針參數(shù)Self,所以定義過(guò)程/函數(shù)時(shí)必須加入一個(gè)假參數(shù)const pSelf: Pointer以保證對(duì)象指針self能夠被傳入。

代碼:

type

    TMyObject = class(TObject)

    private

        FTestEvent: TNotifyEvent;

    public

        procedure ExecTestEvent(Sender: TObject);

        //---

    published

        property TestEvent: TNotifyEvent read FTestEvent write FTestEvent;

    end;

 

//--類方法隱藏了第一個(gè)參數(shù)為對(duì)象的 Self (放在EAX中傳遞)

//--故第一個(gè)參數(shù)為 Self: TObject,第二個(gè)參數(shù)對(duì)應(yīng) TNotifyEvent 的參數(shù)

procedure Gproc(Self: TObject; Sender: TObject);

begin

    ShowMessage('Test');

end;

 

procedure TMyObject.ExecTestEvent(Sender: TObject);

begin

    if Assigned(FTestEvent) then

        FTestEvent(Sender);

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    M: TMethod; //--方法記錄

    AMyObject: TMyObject;

begin

    with M do

    begin

        Code := @Gproc; //--指向方法(這里是全局過(guò)程)地址

        Data := nil; //--指向類實(shí)例(該值對(duì)應(yīng)著 Gproc 調(diào)用時(shí)的 Self 參數(shù)值,可為任意值,這里傳nil

    end;

    //---

    AMyObject := TMyObject.Create;

    try

        AMyObject.TestEvent := TNotifyEvent(M);

        AMyObject.ExecTestEvent(nil);

    finally

        AMyObject.Free;

    end;

end;

說(shuō)明:

1)、第一個(gè)參數(shù)Self: TObject;絕對(duì)不是多余的,雖然你不用它編譯也能通過(guò),還可能執(zhí)行正確,但如果你想在過(guò)程中調(diào)用對(duì)象之真的話,沒(méi)有它可不行。

Delphi默認(rèn)使用寄存器加堆棧的方式傳遞過(guò)程參數(shù),三個(gè)參數(shù)以內(nèi)使用EAX、EDXECX的順序保存參數(shù),三個(gè)以后用堆棧。對(duì)類的方法來(lái)說(shuō),EAX恒定是類實(shí)例指針Self,這樣Sender參數(shù)實(shí)際上放在EDX中做為第二個(gè)參數(shù)傳遞,如下面的代碼:

procedure MyMouseDown(Self: TObject; Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

  ShowMessage(Format('Self: %d, Sender: %d, X: %d, Y: %d', [Integer(Self),

    Integer(Sender), X, Y]));

end;

procedure TForm1.FormCreate(Sender: TObject);

var

  M: TMethod;

begin

  M.Code := @MyMouseDown;

  M.Data := nil;

  Self.OnMouseDown := TMouseEvent(M);

end;

上面的代碼:

Self     -->  EAX

Sender  -->  EDX

Button  -->  CL    // TMouseButton枚舉類型其實(shí)內(nèi)部作Byte

其它三個(gè)放堆棧。

如果把Self: TObject去掉,則MyMouseDown認(rèn)為只有最后兩個(gè)參數(shù)放在堆棧,返回時(shí)POP EIP得到的是錯(cuò)誤的指針,你將看到一個(gè)非法訪問(wèn)內(nèi)存錯(cuò)。

2)、M.Data := nil;我指的是語(yǔ)法上、運(yùn)行時(shí)可為任何值而沒(méi)有錯(cuò)誤。

M.Data保存了方法所對(duì)應(yīng)的對(duì)象指針,用于在調(diào)用該方法時(shí)提供Self這個(gè)隱藏參數(shù),在普通過(guò)程中其實(shí)是沒(méi)有用的。難道你還想在過(guò)程中用Self來(lái)訪問(wèn)一個(gè)按鈕或窗體嗎?M.Data并不是Sender,Sender是由方法(這里是過(guò)程)調(diào)用方指定的。例如VCL源碼:

procedure TControl.DblClick;

begin

  if Assigned(FOnDblClick) then FOnDblClick(Self);

end;

你修改M.Data來(lái)作為Sender其實(shí)是沒(méi)用的。

 

3)、定義M: TMethod只需要賦值時(shí)做一次強(qiáng)制類型轉(zhuǎn)換。Delphi的類型強(qiáng)制轉(zhuǎn)換要求類型相容或長(zhǎng)度一致,TMethod與對(duì)象方法指針是相容的(8字節(jié)),事實(shí)上VCL在調(diào)用事件時(shí),也是按TMethod的結(jié)構(gòu)來(lái)調(diào)用的,而TNofityEvent等類型在本質(zhì)上與TMethod結(jié)構(gòu)相同,但在Delphi這種強(qiáng)類型語(yǔ)言中使用它們可以避免很多錯(cuò)誤。

 

 

示例:方法指針指向過(guò)程/函數(shù)

代碼:

procedure TestMethod(const pSelf: Pointer; AData: Integer);

begin

    ShowMessage(IntToStr(AData));

end;

 

procedure TForm1.Button2Click(Sender: TObject);

type

    TMyMethod = procedure(AData: Integer) of object;

var

    AMyMethod: TMyMethod;

begin

    with TMethod(AMyMethod) do

    begin

        Code := @TestMethod;

        Data := nil;

    end;

    //---

    AMyMethod(1);

end;

 

示例:方法指針指向過(guò)程/函數(shù)

代碼:

type

    TMyObject = class(TObject)

        procedure ExecMethod(const AMsg: string);

    end;

 

procedure TMyObject.ExecMethod(const AMsg: string);

begin

    ShowMessage(AMsg);

end;

 

procedure TestMethod(pSelf: TObject; const AMsg: string);

begin

    ShowMessage(AMsg);

    if pSelf is TMyObject then

        TMyObject(pSelf).ExecMethod(AMsg);

end;

procedure TForm1.Button2Click(Sender: TObject);

var

    AMyObject: TMyObject;

begin

    AMyObject := TMyObject.Create;

    try

        TestMethod(AMyObject,'123');

    finally

        AMyObject.Free;

    end;

end;

代碼:

type

    TFakeEvent = procedure(const AMsg: string) of object;

 

    TMyObject = class(TObject)

    private

        FTestEvent: TFakeEvent;

    public

        constructor Create;

        //---

        procedure ExecTestEvent(const AMsg: string);

        procedure ExecMethod(const AMsg: string);

    end;

 

procedure TestMethod(pSelf: TObject; const AMsg: string);

begin

    ShowMessage(AMsg);

    if pSelf is TMyObject then

        TMyObject(pSelf).ExecMethod(AMsg);

end;

 

constructor TMyObject.Create;

begin

    with TMethod(FTestEvent) do

    begin

        Code := @TestMethod;

        Data := self;

    end;

end;

 

procedure TMyObject.ExecTestEvent(const AMsg: string);

begin

    if Assigned(FTestEvent) then

        FTestEvent(AMsg);

end;

 

procedure TMyObject.ExecMethod(const AMsg: string);

begin

    ShowMessage(AMsg);

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    AMyObject: TMyObject;

begin

    AMyObject := TMyObject.Create;

    try

        AMyObject.ExecTestEvent('123');

    finally

        AMyObject.Free;

    end;

end;

 

示例:方法指針調(diào)用過(guò)程/函數(shù)

代碼:

type

    TFakeEvent = procedure(const AMsg: string) of object;

 

    TMyObject = class(TObject)

    private

        FTestEvent: TFakeEvent;

        procedure TestEvent(const AMsg: string);

    public

        constructor Create;

        //---

        procedure ExecTestEvent(const AMsg: string);

    end;

 

procedure TestMethod(const AMsg: string);

begin

    ShowMessage(AMsg);

end;

 

constructor TMyObject.Create;

begin

    FTestEvent := self.TestEvent;

end;

 

procedure TMyObject.ExecTestEvent(const AMsg: string);

begin

    if Assigned(FTestEvent) then

        FTestEvent(AMsg);

end;

 

procedure TMyObject.TestEvent(const AMsg: string);

begin

    TestMethod(AMsg);

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

    AMyObject: TMyObject;

begin

    AMyObject := TMyObject.Create;

    try

        AMyObject.ExecTestEvent('123');

    finally

        AMyObject.Free;

    end;

end;

 

*對(duì)象指針(代碼)

示例:方法指針的結(jié)構(gòu)

說(shuō)明:DELPHI中的對(duì)象是是一個(gè)32位的指針。

代碼:

procedure TForm1.Button2Click(Sender: TObject);

var

    AObject: TObject;

begin

    AObject := TObject.Create;

    try

        Self.Memo1.Lines.Add('對(duì)象指針大小:' + IntToStr(SizeOf(AObject)));

    finally

        AObject.Free;

    end;

end;

 

 

示例:對(duì)象指針的地址

代碼:

procedure TForm1.Button2Click(Sender: TObject);

var

    pEdit: ^TEdit;

begin

    pEdit := @Edit1;

    //---

    with Self.Memo1.Lines do

    begin

        Add('對(duì)象內(nèi)容:' + IntToStr(Integer(Edit1)));

        Add('對(duì)象指針的內(nèi)容:' + IntToStr(Integer(pEdit)));

        Add('對(duì)象指針指向的內(nèi)容:' + IntToStr(Integer(pEdit^)));

    end;

    //---

    pEdit^.Text := '123';

    pEdit.Text := '123'

end;

說(shuō)明:

在這里還有一個(gè)有趣的現(xiàn)象,我們不但可以用“Edit1^.Text”還可以用“Edit1.Text”方式訪問(wèn)對(duì)象的屬性和方法,其結(jié)果是一樣的,所以在Delphi中只要是對(duì)象都是按指針實(shí)現(xiàn)的。

 

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多