Delphi learning: double-edged sword in OOP

xiaoxiao2021-03-06  42

A few days ago, I saw a very famous commercial control source code and found a very interesting usage:

Integer (xxx): = aaa; ttt (xxx): = BBB; detailed taste, discovery that this usage can often receive unexpected effects: such as:

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;

You will find that you can't change AtestCls.inner.a (compile time Delphi directly, because two Recode assignments in Delphi 7 are Copy Memory rather than simple "inventory"!

Procedure TForm1.Button1Click (Sender: Tobject); Begin with TTestcls.create Do Try // Inner.a: = 10; CAPTION: = TButton (Sender) .caption 'A: =' INTOSTR (Inner.a); Finally .

However, if we know that Delphi is compiled directly Finner when visiting this Inner, then combines the above interesting usage:

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: =' INTOSTOSTR (Inner.a); Finally Free; end; end;

Further, the use of pointers can break through OO to Private protection:

Procedure TForm1.Button4Click (Sender: Tobject); VAR P: ​​Pinteger; Begin with TTESTCLS.CREATE DO TRY P: = @ (ReadonlyValue); Integer (P ^): = 1000; Caption: = TButton (Sender) .caption ' ReadonlyValue: = ' INTOSTR (READOONLYVALUE);

Finally free;

As for "Stepping on the World", it is not going to:

Procedure TForm1.Button5Click (Sender: Tobject); VAR P1, P2: Pinteger; Begin with TTestcls.create Do Try P1: = @ (Inner.a); // Memory FINNER and FREADONLYVALUE is actually only TTESTREC Size byte INTEGER (p2): = Integer (p1) sizeof (TTESTREC); Integer (p2 ^): = 100; caption: = tbutton (sender) .caption 'readonlyValue: =' INTOSTR (READONLYVALUE); FINALLY FREE; END; of course, pointers can not only destroy OO, but also make your code more 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: =' INTOSTR (Inner.a); Finally Free; end; end;

Take a look at the non-OO code in realities: Use the "pointer program" to change TXXX to PXXX, it doesn't have a little impact on the original code, but make it more OO.

转载请注明原文地址:https://www.9cbs.com/read-78601.html

New Post(0)