转载:http://www.cnblogs.com/huangjacky/archive/2009/12/08/1619438.html
技术交流,DH讲解.
之前一篇文章已经讲过对象构造的过程,但是我们那个对象无任何东西,这里我们在已有的基础上面加点儿东西再来看看.
代码改成:
05 |
procedure SayMyName(); |
16 |
procedure TForm3 . btn1Click(Sender: TObject); |
20 |
A:=THuangJacky . Create; |
26 |
constructor THuangJacky . Create; |
31 |
procedure THuangJacky . SayMyName; |
我们可以看到多了一个私有域和公有方法.
构造过程:
1 |
utMain . pas .38 : A:=THuangJacky . Create; |
2 |
004B33E4 B201 mov dl, $01 |
3 |
004B33E6 A1C8324B00 mov eax,[ $004b32c8 ] |
4 |
004B33EB E808000000 call THuangJacky . Create<br><hr> |
04 |
004B33FA 84D2 test dl,dl |
05 |
004B33FC 7408 jz $004b3406 |
06 |
004B33FE 83C4F0 add esp,- $10 |
07 |
004B3401 E8D61EF5FF call @ClassCreate |
08 |
004B3406 8BDA mov ebx,edx |
09 |
004B3408 8BF0 mov esi,eax |
10 |
utMain . pas .46 : FName:= 'HuangJacky' ; |
11 |
004B340A 8D4604 lea eax,[esi+ $04 ] |
12 |
004B340D BA40344B00 mov edx, $004b3440 |
13 |
004B3412 E82D34F5FF call @UStrAsg |
我们可以看到是先构造然后赋值字符串的,@ClassCreate之前的判断都一样的,我们看看$004b3440 地址的数据:
不要忘了我是在D2010下面,所以是Unicode字符串.
05 |
004052DF 84D2 test dl,dl |
06 |
004052E1 7C03 jl $004052e6 |
07 |
004052E3 FF50F4 call dword ptr [eax- $0c ] |
08 |
004052E6 31D2 xor edx,edx |
09 |
004052E8 8D4C2410 lea ecx,[esp+ $10 ] |
10 |
004052EC 648B1A mov ebx,fs:[edx] |
11 |
004052EF 8919 mov [ecx],ebx |
12 |
004052F1 896908 mov [ecx+ $08 ],ebp |
13 |
004052F4 C7410405534000 mov [ecx+ $04 ], $00405305 |
14 |
004052FB 89410C mov [ecx+ $0c ],eax |
15 |
004052FE 64890A mov fs:[edx],ecx |
这个函数还是一样的.我们不需要看了,从这里跳吧004052E3
03 |
00404D41 8BD8 mov ebx,eax |
04 |
00404D43 8BC3 mov eax,ebx |
05 |
00404D45 E826000000 call TObject . InstanceSize |
06 |
00404D4A E885F4FFFF call @GetMem |
07 |
00404D4F 8BD0 mov edx,eax |
08 |
00404D51 8BC3 mov eax,ebx |
09 |
00404D53 E85C000000 call TObject . InitInstance |
12 |
00404D5A 8BC0 mov eax,eax |
还是到这里来了,貌似一路上什么都没有变.但是我推想TObject.InstanceSize返回值会有变化,毕竟多了一个私有成员,但是@GetMem肯定不变,TObject.InitInstance也会变化,毕竟有方法了.跟进验证
果然现在TObject.InstanceSize返回值是$0C了,也就是12,上一次什么都没有是8,现在多了4,多了一个指针地址,难道这个指针就是字符串指针一会儿验证下?
接下来我们直接进入InitInstance看看.有什么变化没有?
我跟进去发现没有变化,这个方法不在IntfTable里面的.我们看看初始化完成后的对象数据.
我们看看$004b3320是什么东西.
这里看上去像是THuangJacky的内存地址,那我们最先看见的[$004b32c8]是什么?我们注意地址加上[]就是地址指向的值.
是的,就是指向这里的.
我们让它Create完后再来看对象的数据,OK?
变化了,第二地址会是什么呢?
果然是第一个成员变量的值.
有朋友要问那么SayMyName这个方法的信息存在哪里的呢?这个方法我们要知道是和类挂钩的,所以肯定在类的内存信息块里面的.我们到类信息块去看看,SayMyName字符串前面有4个字节$004B3464
1 |
utMain . pas .52 : ShowMessage(FName); |
2 |
004B3464 8B4004 mov eax,[eax+ $04 ] |
3 |
004B3467 E8AC4CFBFF call ShowMessage |
最后来做个试验,我们给类里面再加一个私有成员,然后实现ClassHack,哈哈,违反面向对象的方法
06 |
procedure SayMyName(); |
18 |
procedure TForm3 . btn1Click(Sender: TObject); |
23 |
A:=THuangJacky . Create; |
24 |
Pi:=PInteger( Integer (A)+ 8 ); |
25 |
ShowMessage(IntToStr(Pi^)); |
32 |
constructor THuangJacky . Create; |
38 |
procedure THuangJacky . SayMyAge; |
40 |
ShowMessage(IntToStr(FAge)); |
43 |
procedure THuangJacky . SayMyName; |
看下新对象的内存和类的内存:
对象的:
类的:
注意看方法前面的地址.哈哈.
今天就说到这里,或许有朋友问这样研究有什么意思.下一篇文章就讲单例模式,这个总有用吧,Delphi里面单例模式就要和我们讲的这些知识挂上钩了,因为Delphi很特别哟.
好,下次见,我是DH.