Environment: XPSP3 VS2005
Today the black general to the candidate out of a C + + constructor call virtual function, the specific topic is more complex than the title, the general situation can see the following code:
[CPP]View PlainCopy
- Class Base
- {
- Public
- Base ()
- {
- Fuction ();
- }
- virtual void fuction ()
- {
- cout << "base::fuction" << Endl;
- }
- };
- Class A: Public Base
- {
- Public
- A ()
- {
- Fuction ();
- }
- virtual void fuction ()
- {
- cout << "a::fuction" << Endl;
- }
- };
- What is the output of defining an object of a?
- A;
First answer the question of the title, the call is of course no problem, but to get the results you want? Or what kind of results do you want?
Some say it will output:
[HTML]View PlainCopy
- A::fuction
- A::fuction
If this is the case, first we review the C + + object model in the construction sequence, when constructing a subclass object, the first will construct its base class, if there is a multi-level inheritance relationship, in fact, from the top-level base class down-to-bottom structure (virtual inheritance, multiple inheritance is not discussed here), if the above situation is output , that is, when the base is constructed, that is, when calling Fuction in the constructor of base, the fuction of subclass A is called, and a is not actually started, so the behavior of the function is completely unpredictable, so this is obviously not the case, the actual output is:
[HTML]View PlainCopy
- Base::fuction
- A::fuction
It is said to be the last output in Java (it feels a bit strange).
Let's take a closer look at what's going on. In the constructor of a, the constructor of base is called first, and the constructor of base is as follows:
Class Base
{
Public
Base ()
00411600 Push EBP
00411601 mov Ebp,esp
00411603 Sub Esp,0cch
00411609 push EBX
0041160A push ESI
0041160B Push EDI
0041160C push ECX
0041160D Lea EDI,[EBP-0CCH]
00411613 mov ecx,33h
00411618 mov eax,0cccccccch
0041161D Rep STOs dword ptr Es:[edi]
0041161F pop ECX
00411620 mov dword ptr [EBP-8],ECX
00411623 mov Eax,dword ptr [this]
00411626 mov dword ptr [eax],offset Base:: ' vftable ' (41770Ch)
{
Fuction ();
0041162C mov Ecx,dword ptr [this]
0041162F call Base::fuction (4111a9h)
}
00411634 mov eax,dword ptr [this]
00411637 pop edi
00411638 pop esi
00411639 pop ebx
0041163a add esp,0CCh
00411640 cmp ebp,esp
00411642 call @ILT +460 (__RTC_CHECKESP) (4111d1h)
00411647 mov esp,ebp
00411649 pop ebp
0041164a ret
From the single-step tracking, notice the black bold part of the assembly code, ECX is the address of the object (0X0012FF60, the case on my machine, there is a picture of the truth), the first is to set vtable address to the first four bytes of the object (different compilers may be different), Then directly call the Base::fuction function, and there is no virtual mechanism, and we look at the state of the virtual table, the virtual table has been filled with 0x4111a9, note the address of the virtual table 0x0041770c, At this point, the object address 0x0012ff60 the first four bytes to be stored is the 0x0041770c.
Continue tracing, the process goes back to the constructor of a, again notice the bold part of the code, from the base class base of the constructor returned, in A's constructor, the virtual table pointer is reset, now the virtual table pointer is (0x417700h), the same call Fuction when a direct call to a:: The Fuction function does not use a virtual mechanism, and the 0x41110e where the virtual table 0x417700h points is the a::fuction address.
Class A:public Base
{
Public
A ()
00411590 Push EBP
00411591 mov Ebp,esp
00411593 Sub Esp,0cch
00411599 push EBX
0041159A push ESI
0041159B Push EDI
0041159C push ECX
0041159D Lea EDI,[EBP-0CCH]
004115A3 mov ecx,33h
004115A8 mov eax,0cccccccch
004115AD Rep STOs dword ptr Es:[edi]
004115AF pop ECX
004115B0 mov dword ptr [EBP-8],ECX
004115B3 mov Ecx,dword ptr [this]
004115b6 call Base::base (411140h)
004115BB mov Eax,dword ptr [this]
004115BE mov dword ptr [eax],offset A:: ' vftable ' (417700h)
{
Fuction ();
004115C4 mov Ecx,dword ptr [this]
004115c7 call A::fuction (41110Eh)
}
004115CC mov Eax,dword ptr [this]
004115CF Pop EDI
004115d0 pop ESI
004115D1 pop ebx
004115D2 Add ESP,0CCH
004115D8 CMP EBP,ESP
004115DA call @ILT +460 (__RTC_CHECKESP) (4111D1H)
004115DF mov esp,ebp
004115E1 Pop EBP
004115E2 ret
In fact, it is so simple.
http://blog.csdn.net/magictong/article/details/6734241
Can a constructor in C + + call a virtual function? (The answer is syntax Yes, output error), but Java can actually