| 導購 | 订阅 | 在线投稿
分享
 
 
 

Delphi學習:OOP 中的雙刃劍

來源:互聯網網民  2006-12-16 17:27:43  評論

前幾天看一份非常有名的商業控件的源碼,發現一個非常有趣的用法:

Integer(xxx) := aaa;

Tttt(xxx) := bbb;

細細品味,發現利用這種用法往往可以收到意想不到的效果:

比如:

TTestRec = record

A, B, C: Integer;

end;

TTestCls = class

private

FInner: TTestRec;

FReadOnlyValue: Integer;

function GetNewInner: PTestRec;

public

property Inner: TTestRec read FInner write FInner;

property NewInner: PTestRec read GetNewInner;

property ReadOnlyValue: Integer read FReadOnlyValue;

end;

你會發現,直接的你是改不了 aTestCls.Inner.A 的(編譯時 delphi 直接報錯,因爲 delphi 7 中兩個 recode 賦值是 copy memory 而不是簡單的「傳址」!

procedure TForm1.Button1Click(Sender: TObject);

begin

with TTestCls.Create do

try

// Inner.A := 10;

Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A);

finally

Free;

end;

end;

可是,如果我們知道在訪問這個 Inner 時 delphi 在編譯直接 FInner 的地址,那麽,結合上面那種有趣的用法:

procedure TForm1.Button3Click(Sender: TObject);

var

p: PInteger;

begin

with TTestCls.Create do

try

p := @(Inner.A);

Integer(p^) := 100;

Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A);

finally

Free;

end;

end;

更進一步,利用指針竟然可以突破 oo 對 private 的保護:

procedure TForm1.Button4Click(Sender: TObject);

var

p: PInteger;

begin

with TTestCls.Create do

try

p := @(ReadOnlyValue);

Integer(p^) := 1000;

Caption := TButton(Sender).Caption + ' ReadOnlyValue := ' + IntToStr(ReadOnlyValue);

||||||

finally

Free;

end;

end;

至于「踩過界」那更不在話下:

procedure TForm1.Button5Click(Sender: TObject);

var

p1, p2: PInteger;

begin

with TTestCls.Create do

try

p1 := @(Inner.A);

// 內存中 FInner 與 FReadOnlyValue 其實只差 TTestRec 大小個字節

Integer(p2) := Integer(p1) + SizeOf(TTestRec);

Integer(p2^) := 100;

Caption := TButton(Sender).Caption + ' ReadOnlyValue := ' + IntToStr(ReadOnlyValue);

finally

Free;

end;

end;

當然,指針不但可以破壞 oo,也能使您的代碼更加的 oo:

TTestRec = record

A, B, C: Integer;

end;

PTestRec = ^TTestRec;

TTestCls = class

private

FInner: TTestRec;

FReadOnlyValue: Integer;

function GetNewInner: PTestRec;

public

property Inner: TTestRec read FInner write FInner;

property NewInner: PTestRec read GetNewInner;

property ReadOnlyValue: Integer read FReadOnlyValue;

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

with TTestCls.Create do

try

NewInner.A := 10;

Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A);

finally

Free;

end;

end;

看看現實中的非 oo 的代碼:

利用「指針方案」把 Txxx 改成 Pxxx 後竟然對原來的代碼一點影響都沒有,而使之更加的 oo

 
特别声明:以上内容(如有图片或视频亦包括在内)为网络用户发布,本站仅提供信息存储服务。
 
 前幾天看一份非常有名的商業控件的源碼,發現一個非常有趣的用法:   Integer(xxx) := aaa;   Tttt(xxx) := bbb;   細細品味,發現利用這種用法往往可以收到意想不到的效果:   比如: TTestRec = record A, B, C: Integer; end; TTestCls = class private FInner: TTestRec; FReadOnlyValue: Integer; function GetNewInner: PTestRec; public property Inner: TTestRec read FInner write FInner; property NewInner: PTestRec read GetNewInner; property ReadOnlyValue: Integer read FReadOnlyValue; end;   你會發現,直接的你是改不了 aTestCls.Inner.A 的(編譯時 delphi 直接報錯,因爲 delphi 7 中兩個 recode 賦值是 copy memory 而不是簡單的「傳址」! procedure TForm1.Button1Click(Sender: TObject); begin with TTestCls.Create do try // Inner.A := 10; Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A); finally Free; end; end;   可是,如果我們知道在訪問這個 Inner 時 delphi 在編譯直接 FInner 的地址,那麽,結合上面那種有趣的用法: procedure TForm1.Button3Click(Sender: TObject); var p: PInteger; begin with TTestCls.Create do try p := @(Inner.A); Integer(p^) := 100; Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A); finally Free; end; end;   更進一步,利用指針竟然可以突破 oo 對 private 的保護: procedure TForm1.Button4Click(Sender: TObject); var p: PInteger; begin with TTestCls.Create do try p := @(ReadOnlyValue); Integer(p^) := 1000; Caption := TButton(Sender).Caption + ' ReadOnlyValue := ' + IntToStr(ReadOnlyValue); |||||| finally Free; end; end;   至于「踩過界」那更不在話下: procedure TForm1.Button5Click(Sender: TObject); var p1, p2: PInteger; begin with TTestCls.Create do try p1 := @(Inner.A); // 內存中 FInner 與 FReadOnlyValue 其實只差 TTestRec 大小個字節 Integer(p2) := Integer(p1) + SizeOf(TTestRec); Integer(p2^) := 100; Caption := TButton(Sender).Caption + ' ReadOnlyValue := ' + IntToStr(ReadOnlyValue); finally Free; end; end;   當然,指針不但可以破壞 oo,也能使您的代碼更加的 oo: TTestRec = record A, B, C: Integer; end; PTestRec = ^TTestRec; TTestCls = class private FInner: TTestRec; FReadOnlyValue: Integer; function GetNewInner: PTestRec; public property Inner: TTestRec read FInner write FInner; property NewInner: PTestRec read GetNewInner; property ReadOnlyValue: Integer read FReadOnlyValue; end; procedure TForm1.Button2Click(Sender: TObject); begin with TTestCls.Create do try NewInner.A := 10; Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A); finally Free; end; end;   看看現實中的非 oo 的代碼:   利用「指針方案」把 Txxx 改成 Pxxx 後竟然對原來的代碼一點影響都沒有,而使之更加的 oo
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有