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

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
󰈣󰈤
日版宠物情人插曲《Winding Road》歌词

日版宠物情人2017的插曲,很带节奏感,日语的,女生唱的。 最后听见是在第8集的时候女主手割伤了,然后男主用嘴帮她吸了一下,插曲就出来了。 歌手:Def...

兄弟共妻,我成了他们夜里的美食

老钟家的两个儿子很特别,就是跟其他的人不太一样,魔一般的执着。兄弟俩都到了要结婚的年龄了,不管自家老爹怎么磨破嘴皮子,兄弟俩说不娶就不娶,老父母为兄弟两操碎了心...

 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
王朝网络微信公众号
微信扫码关注本站公众号 wangchaonetcn
 
  免责声明:本文仅代表作者个人观点,与王朝网络无关。王朝网络登载此文出于传递更多信息之目的,并不意味著赞同其观点或证实其描述,其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有