从汇编角度看继承和虚函数

#include "stdafx.h"
#include <stdio.h>

class Base
{
public:
    virtual int basevt()
 {
    return 1;
 }
};

class Inherit:public Base
{
   public:
   int basevt()
 {
     return 2;
 };
};

int main(int argc, char* argv[])
{
   Inherit inherit;
   printf("%d\n", inherit.basevt());
   return 0;
}

反汇编后:

.text:00401030                 push    ebp
.text:00401031                 mov     ebp, esp
.text:00401033                 sub     esp, 44h
.text:00401036                 push    ebx
.text:00401037                 push    esi
.text:00401038                 push    edi
.text:00401039                 lea     edi, [ebp+var_44]
.text:0040103C                 mov     ecx, 11h
.text:00401041                 mov     eax, 0CCCCCCCCh
.text:00401046                 rep stosd
.text:00401048                 lea     ecx, [ebp+var_4]
.text:0040104B                 call    j_Inherit__Inherit                     ;调用子类的构造函数
.text:00401050                 lea     ecx, [ebp+var_4]                    ;将子类this指针作隐含参数传入
.text:00401053                 call    j_Inherit__basevt                    ;调用子类的basevt虚函数;
.text:00401058                 push    eax
.text:00401059                 push    offset aD       ; "%d\n"
.text:0040105E                 call    printf
.text:00401063                 add     esp, 8
.text:00401066                 xor     eax, eax
.text:00401068                 pop     edi
.text:00401069                 pop     esi
.text:0040106A                 pop     ebx
.text:0040106B                 add     esp, 44h
.text:0040106E                 cmp     ebp, esp
.text:00401070                 call    __chkesp
.text:00401075                 mov     esp, ebp
.text:00401077                 pop     ebp
.text:00401078                 retn
----------------------------------------------------------------------------------------

子类构造函数中:

.text:004010C0                 push    ebp
.text:004010C1                 mov     ebp, esp
.text:004010C3                 sub     esp, 44h
.text:004010C6                 push    ebx
.text:004010C7                 push    esi
.text:004010C8                 push    edi
.text:004010C9                 push    ecx
.text:004010CA                 lea     edi, [ebp+var_44]
.text:004010CD                 mov     ecx, 11h
.text:004010D2                 mov     eax, 0CCCCCCCCh
.text:004010D7                 rep stosd
.text:004010D9                 pop     ecx
.text:004010DA                 mov     [ebp+var_4], ecx
.text:004010DD                 mov     ecx, [ebp+var_4]
.text:004010E0                 call    j_Base__Base                                                    ;调用父类构造函数
.text:004010E5                 mov     eax, [ebp+var_4]                                              ;子类this指针
.text:004010E8                 mov     dword ptr [eax], offset ??_7Inherit@@6B@ ; const Inherit::`vftable'         ;覆盖父类虚函数表指针
.text:004010EE                 mov     eax, [ebp+var_4]                                              ;返回this指针
.text:004010F1                 pop     edi
.text:004010F2                 pop     esi
.text:004010F3                 pop     ebx
.text:004010F4                 add     esp, 44h
.text:004010F7                 cmp     ebp, esp
.text:004010F9                 call    __chkesp
.text:004010FE                 mov     esp, ebp
.text:00401100                 pop     ebp
.text:00401101                 retn
-------------------------------------------------------------------------------------------------------------------

父类构造函数:

.text:0040D7A0                 push    ebp
.text:0040D7A1                 mov     ebp, esp
.text:0040D7A3                 sub     esp, 44h
.text:0040D7A6                 push    ebx
.text:0040D7A7                 push    esi
.text:0040D7A8                 push    edi
.text:0040D7A9                 push    ecx
.text:0040D7AA                 lea     edi, [ebp+var_44]
.text:0040D7AD                 mov     ecx, 11h
.text:0040D7B2                 mov     eax, 0CCCCCCCCh
.text:0040D7B7                 rep stosd
.text:0040D7B9                 pop     ecx
.text:0040D7BA                 mov     [ebp+var_4], ecx
.text:0040D7BD                 mov     eax, [ebp+var_4]                                             ;子类this指针.
.text:0040D7C0                 mov     dword ptr [eax], offset ??_7Base@@6B@ ; const Base::`vftable'  虚函数表指针写入this指针.
.text:0040D7C6                 mov     eax, [ebp+var_4]                                             ;返回this指针
.text:0040D7C9                 pop     edi
.text:0040D7CA                 pop     esi
.text:0040D7CB                 pop     ebx
.text:0040D7CC                 mov     esp, ebp
.text:0040D7CE                 pop     ebp
.text:0040D7CF                 retn
------------------------------------------------------------------------------------------------------

basevt函数:

.text:00401090                 push    ebp
.text:00401091                 mov     ebp, esp
.text:00401093                 sub     esp, 44h
.text:00401096                 push    ebx
.text:00401097                 push    esi
.text:00401098                 push    edi
.text:00401099                 push    ecx
.text:0040109A                 lea     edi, [ebp+var_44]
.text:0040109D                 mov     ecx, 11h
.text:004010A2                 mov     eax, 0CCCCCCCCh
.text:004010A7                 rep stosd
.text:004010A9                 pop     ecx
.text:004010AA                 mov     [ebp+var_4], ecx
.text:004010AD                 mov     eax, 2
.text:004010B2                 pop     edi
.text:004010B3                 pop     esi
.text:004010B4                 pop     ebx
.text:004010B5                 mov     esp, ebp
.text:004010B7                 pop     ebp
.text:004010B8                 retn

综上:

子类继承父类,首先是先调用子类的构造函数分配内存空间,然后调用父类构造函数,将父类的虚函数表指针写入this指针.

之后是子类覆盖父类的虚函数表指针,导致,子类调用父类相同的函数时,将是子类的函数.

posted @ 2009-12-08 19:09  SaikSy  阅读(253)  评论(0编辑  收藏  举报