- 帖子
- 164
- 积分
- 164
- 经验
- 164 点
- 威望
- 0 点
- 金钱
- 9 NG
- 魅力
- 42
- 性别
- 男
- 注册时间
- 2003-9-4
我们约会吧!
|
10#
发表于 2003-2-20 11:13
| 只看该作者
Re:【讨论】编程
ask:
对于C++来说,最强的功能是指针,最容易犯错的也是指针。本例中,关键是二个类的结构是完全相同的。这时候C++的编译器会根据最适合的方法来解释:
girl *the_pretty_home = &pretty;//女孩说:我不要离开家……不嫁给你(真的?)!
boy *the_handsome_home = &pretty;//男孩说:来我家吧,我爱你!
换句话说,这时,编译器并不知道the_handsome_home,the_pretty_home 到底是boy还是girl。必须根据具体的方法调用时才能确定。
。上例的结果实际上,严格来说并不准确,只能说对VC是正确的,对不同的编译器会有不同的处理方法,其结果也不同。
answer1:
我试过了,在C++Builder的编译器中,结果是一样的。
answer2:
我们需要更深层次来讨论这个问题,我反汇编了相关代码,这里是main()段:
:00401060 55 push ebp
:00401061 8BEC mov ebp, esp
:00401063 83EC10 sub esp, 00000010
:00401066 8D45FC lea eax, dword ptr [ebp-04] ;[ebp-04]为&pretty
:00401069 8945F8 mov dword ptr [ebp-08], eax ;[ebp-08]为[the_pretty_home]
;girl *the_pretty_home = &pretty;
:0040106C 8D4DFC lea ecx, dword ptr [ebp-04]
:0040106F 894DF0 mov dword ptr [ebp-10], ecx ;[ebp-10]为[the_handsome_home]
;boy *the_handsome_home = &pretty;
:00401072 6866665042 push 42506666
:00401077 8B4DF0 mov ecx, dword ptr [ebp-10]
:0040107A E890FFFFFF call 0040100F
;the_handsome_home->LoveYou(52.1f);
:0040107F 6A34 push 00000034
:00401081 8B4DF8 mov ecx, dword ptr [ebp-08]
:00401084 E890FFFFFF call 00401019
;the_pretty_home ->LoveYou(52.1f);
:00401089 6866665042 push 42506666
:0040108E 8B4DF0 mov ecx, dword ptr [ebp-10]
:00401091 E86FFFFFFF call 00401005
;the_handsome_home->KissYou(52.1f);
:00401096 6866665042 push 42506666
:0040109B 8B4DF8 mov ecx, dword ptr [ebp-08]
:0040109E E87BFFFFFF call 0040101E
;the_pretty_home ->KissYou(52.1f);
:004010A3 8BE5 mov esp, ebp
:004010A5 5D pop ebp
:004010A6 C3 ret
可以看到,the_pretty_home和the_handsome_home指针的数值的确是相同的,都指向了&pretty
但是为什么
the_handsome_home->LoveYou(52.1f);和
the_pretty_home->LoveYou(52.1f);
却得到了不同的结果。汇编代码提示出,在调用成员函数的时候已经被编译成不同的地址:一个是call 0040100F,一个是call 00401019。
经过函数跳转表后,call 0040100F是下面的代码:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040100F(U)
|
:004010C0 55 push ebp
:004010C1 8BEC mov ebp, esp
:004010C3 51 push ecx
:004010C4 894DFC mov dword ptr [ebp-04], ecx
:004010C7 6814104000 push 00401014
* Possible StringData Ref from Data Obj ->"Preety, I love you, marry me!"
|
:004010CC 6850BD4100 push 0041BD50
:004010D1 B9E0F44100 mov ecx, 0041F4E0
:004010D6 E875030000 call 00401450
:004010DB 8BC8 mov ecx, eax
:004010DD E81EFFFFFF call 00401000
:004010E2 8BE5 mov esp, ebp
:004010E4 5D pop ebp
:004010E5 C20400 ret 0004
非常明显,这就是boy类的成员函数LoveYou();而call 00401019同样可以证明是girl类的成员函数LoveYou();
最后我的结论是:上面的隐藏规则在编译的时候就确定和实现了,也即是“静态绑定”。C++类的指针不仅和它的值有关系,还和它的类别有关系。也就是说,编译器一定要知道the_handsome_home,the_pretty_home 到底是boy还是girl,才能确定具体的方法调用。这和C具有重大的区别。 |
|