子类构造函数先调用父类。子类保留父类一块空间。
以一个例子分析:
class A
{
public:
A() { }
~A() { cout<<"~A"<<endl; }
};
class B:public A
{
public:
B(A &a):_a(a)
{
}
~B()
{
cout<<"~B"<<endl;
}
private:
A _a;
};
int main(void)
{
A a; //很简单,定义a的时候调用了一次构造函数
B b(a);
}
输出:
A construct
A construct
const A&
~B
~A
~A
~A
下面是反汇编代码
1: #include <iostream>
2: using namespace std;
3: class A
4: {
5: public:
6: A()
00401240 push ebp
00401241 mov ebp,esp
00401243 sub esp,44h
00401246 push ebx
00401247 push esi
00401248 push edi
00401249 push ecx
0040124A lea edi,[ebp-44h]
0040124D mov ecx,11h
00401252 mov eax,0CCCCCCCCh
00401257 rep stos dword ptr [edi]
00401259 pop ecx
0040125A mov dword ptr [ebp-4],ecx
7: {
8: cout << "A construct" << endl;
0040125D push offset @ILT+35(std::endl) (00401028)
00401262 push offset string "A construct" (0043201c)
00401267 push offset std::cout (00439528)
0040126C call @ILT+180(std::operator<<) (004010b9)
00401271 add esp,8
00401274 mov ecx,eax
00401276 call @ILT+120(std::basic_ostream<char,std::char_traits<char> >::operator<<) (0040107d)
9: }
0040127B mov eax,dword ptr [ebp-4]
0040127E pop edi
0040127F pop esi
00401280 pop ebx
00401281 add esp,44h
00401284 cmp ebp,esp
00401286 call __chkesp (004096e0)
0040128B mov esp,ebp
0040128D pop ebp
0040128E ret
10: A operator=(const A &a)
11: {
12: cout << "operator = " << endl;
13: return a;
14: }
15: A(const A& a) 复制构造函数
004013B0 push ebp
004013B1 mov ebp,esp
004013B3 sub esp,44h
004013B6 push ebx
004013B7 push esi
004013B8 push edi
004013B9 push ecx
004013BA lea edi,[ebp-44h]
004013BD mov ecx,11h
004013C2 mov eax,0CCCCCCCCh
004013C7 rep stos dword ptr [edi]
004013C9 pop ecx
004013CA mov dword ptr [ebp-4],ecx
16: {
17: cout << "const A&" << endl;
004013CD push offset @ILT+35(std::endl) (00401028)
004013D2 push offset string "const A&" (00432030)
004013D7 push offset std::cout (00439528)
004013DC call @ILT+180(std::operator<<) (004010b9)
004013E1 add esp,8
004013E4 mov ecx,eax
004013E6 call @ILT+120(std::basic_ostream<char,std::char_traits<char> >::operator<<) (0040107d)
18: }
004013EB mov eax,dword ptr [ebp-4]
004013EE pop edi
004013EF pop esi
004013F0 pop ebx
004013F1 add esp,44h
004013F4 cmp ebp,esp
004013F6 call __chkesp (004096e0)
004013FB mov esp,ebp
004013FD pop ebp
004013FE ret 4
19: ~A()
20: {
004012B0 push ebp
004012B1 mov ebp,esp
004012B3 sub esp,44h
004012B6 push ebx
004012B7 push esi
004012B8 push edi
004012B9 push ecx
004012BA lea edi,[ebp-44h]
004012BD mov ecx,11h
004012C2 mov eax,0CCCCCCCCh
004012C7 rep stos dword ptr [edi]
004012C9 pop ecx
004012CA mov dword ptr [ebp-4],ecx
21: cout<<"~A"<<endl;
004012CD push offset @ILT+35(std::endl) (00401028)
004012D2 push offset string "~A" (0043202c)
004012D7 push offset std::cout (00439528)
004012DC call @ILT+180(std::operator<<) (004010b9)
004012E1 add esp,8
004012E4 mov ecx,eax
004012E6 call @ILT+120(std::basic_ostream<char,std::char_traits<char> >::operator<<) (0040107d)
22: }
004012EB pop edi
004012EC pop esi
004012ED pop ebx
004012EE add esp,44h
004012F1 cmp ebp,esp
004012F3 call __chkesp (004096e0)
004012F8 mov esp,ebp
004012FA pop ebp
004012FB ret
23: };
24:
25: class B:public A
26: {
27: public:
28: B(A &a):_a(a)
29: {
00401310 push ebp
00401311 mov ebp,esp
00401313 push 0FFh
00401315 push offset __ehhandler$??0B@@QAE@AAVA@@@Z (0041fd79)
0040131A mov eax,fs:[00000000]
00401320 push eax
00401321 mov dword ptr fs:[0],esp
00401328 sub esp,44h
0040132B push ebx
0040132C push esi
0040132D push edi
0040132E push ecx
0040132F lea edi,[ebp-50h]
00401332 mov ecx,11h
00401337 mov eax,0CCCCCCCCh
0040133C rep stos dword ptr [edi]
0040133E pop ecx
0040133F mov dword ptr [ebp-10h],ecx
00401342 mov ecx,dword ptr [ebp-10h]
00401345 call @ILT+80(A::A) (00401055) 普通构造函数 B类有A类对象。
0040134A mov dword ptr [ebp-4],0
00401351 mov eax,dword ptr [ebp+8]
00401354 push eax
00401355 mov ecx,dword ptr [ebp-10h]
00401358 call @ILT+165(A::A) (004010aa) 复制构造函数
30: // _a = a;
31: }
0040135D mov dword ptr [ebp-4],0FFFFFFFFh
00401364 mov eax,dword ptr [ebp-10h]
00401367 mov ecx,dword ptr [ebp-0Ch]
0040136A mov dword ptr fs:[0],ecx
00401371 pop edi
00401372 pop esi
00401373 pop ebx
00401374 add esp,50h
00401377 cmp ebp,esp
00401379 call __chkesp (004096e0)
0040137E mov esp,ebp
00401380 pop ebp
00401381 ret 4
32: ~B()
33: {
00401420 push ebp
00401421 mov ebp,esp
00401423 push 0FFh
00401425 push offset __ehhandler$??1B@@QAE@XZ (0041fda2)
0040142A mov eax,fs:[00000000]
00401430 push eax
00401431 mov dword ptr fs:[0],esp
00401438 sub esp,44h
0040143B push ebx
0040143C push esi
0040143D push edi
0040143E push ecx
0040143F lea edi,[ebp-50h]
00401442 mov ecx,11h
00401447 mov eax,0CCCCCCCCh
0040144C rep stos dword ptr [edi]
0040144E pop ecx
0040144F mov dword ptr [ebp-10h],ecx
00401452 mov dword ptr [ebp-4],1
34: cout<<"~B"<<endl;
00401459 push offset @ILT+35(std::endl) (00401028)
0040145E push offset string "~B" (0043203c)
00401463 push offset std::cout (00439528)
00401468 call @ILT+180(std::operator<<) (004010b9)
0040146D add esp,8
00401470 mov ecx,eax
00401472 call @ILT+120(std::basic_ostream<char,std::char_traits<char> >::operator<<) (0040107d)
35: }
00401477 mov byte ptr [ebp-4],0
0040147B mov ecx,dword ptr [ebp-10h]
0040147E call @ILT+110(A::~A) (00401073)
00401483 mov dword ptr [ebp-4],0FFFFFFFFh
0040148A mov ecx,dword ptr [ebp-10h]
0040148D call @ILT+110(A::~A) (00401073)
00401492 mov ecx,dword ptr [ebp-0Ch]
00401495 mov dword ptr fs:[0],ecx
0040149C pop edi
0040149D pop esi
0040149E pop ebx
0040149F add esp,50h
004014A2 cmp ebp,esp
004014A4 call __chkesp (004096e0)
004014A9 mov esp,ebp
004014AB pop ebp
004014AC ret
36: private:
37: A _a;
38: };
39:
40: int main(void)
41: {
00401190 push ebp
00401191 mov ebp,esp
00401193 push 0FFh
00401195 push offset __ehhandler$_main (0041fd59)
0040119A mov eax,fs:[00000000]
004011A0 push eax
004011A1 mov dword ptr fs:[0],esp
004011A8 sub esp,4Ch
004011AB push ebx
004011AC push esi
004011AD push edi
004011AE lea edi,[ebp-58h]
004011B1 mov ecx,13h
004011B6 mov eax,0CCCCCCCCh
004011BB rep stos dword ptr [edi]
42: A a; //很简单,定义a的时候调用了一次构造函数
004011BD lea ecx,[ebp-10h]
004011C0 call @ILT+80(A::A) (00401055)
004011C5 mov dword ptr [ebp-4],0
43: B b(a);
004011CC lea eax,[ebp-10h]
004011CF push eax
004011D0 lea ecx,[ebp-14h]
004011D3 call @ILT+155(B::B) (004010a0)
44: return 0;
004011D8 mov dword ptr [ebp-18h],0
004011DF lea ecx,[ebp-14h]
004011E2 call @ILT+130(B::~B) (00401087)
004011E7 mov dword ptr [ebp-4],0FFFFFFFFh
004011EE lea ecx,[ebp-10h]
004011F1 call @ILT+110(A::~A) (00401073)
004011F6 mov eax,dword ptr [ebp-18h]
45: }
004011F9 mov ecx,dword ptr [ebp-0Ch]
004011FC mov dword ptr fs:[0],ecx
00401203 pop edi
00401204 pop esi
00401205 pop ebx
00401206 add esp,58h
00401209 cmp ebp,esp
0040120B call __chkesp (004096e0)
00401210 mov esp,ebp
00401212 pop ebp
00401213 ret
@ILT+145(_main):
00401096 jmp main (00401190)
@ILT+155(??0B@@QAE@AAVA@@@Z):
004010A0 jmp B::B (00401310)
@ILT+165(??0A@@QAE@ABV0@@Z):
004010AA jmp A::A (004013b0) 复制构造函数
@ILT+110(??1A@@QAE@XZ):
00401073 jmp A::~A (004012b0)
@ILT+130(??1B@@QAE@XZ):
00401087 jmp B::~B (00401420)
@ILT+80(??0A@@QAE@XZ):
00401055 jmp A::A (00401240) 普通构造函数