Can constructors in C ++ call virtual functions?

Source: Internet
Author: User

Environment: xpsp3 vs2005

Today, Mr. Hei gave the applicant a question about calling a virtual function in the C ++ constructor. The specific question is more complex than the title. For details, refer to the following code:

Class base {public: Base () {fuction ();} virtual void fuction () {cout <"base: fuction" <Endl ;}; Class: public base {public: A () {fuction ();} virtual void fuction () {cout <"A: fuction" <Endl ;}}; // What will be output when an object of A is defined in this way? A;

First, answer the question of the title. Of course there is no problem with the call, but is the expected result obtained? Or what kind of results do you want?

Someone said it would output:

A::FuctionA::Fuction

In this case, we will first review the construction order in the C ++ object model. When constructing a subclass object, we will first construct its base class. If there is a multi-layer inheritance relationship, in fact, it will be constructed from the top-level base class layer by layer (Virtual inheritance and multi-inheritance are not discussed here). If the output is based on the above situation, that is, when constructing the base, that is, when the base constructor calls fuction, it calls the fuction of subclass A. In fact, a has not yet started to construct, so that the function behavior is completely unpredictable, obviously this is not the case. The actual output result is:

Base::FuctionA::Fuction

It is said that it is an output in Java (which is a bit incredible ).

Let's take a single step to see what happened? In the constructor of A, the base constructor will be called first. The constructor of the 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, 33 H
00411618 mov eax, 0 cccccccch
0043661d rep STOs dword ptr es: [EDI]
00400001f pop ECx
00411620 mov dword ptr [ebp-8], ECx
00411623 mov eax, dword ptr [this]
00411626 mov dword ptr [eax], offset base: 'vftable' (000070ch)
{
Fuction ();
0043662c 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
004100003a 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 perspective of single-step tracking, pay attention to the Black and bold assembly code. ECx stores the object address (0x0012ff60, my machine's situation, there is a picture of the truth ), first, set the vtable address to the first four bytes of the object (different compilers may be different), and then directly call the base: fuction function without a virtual mechanism, now we can see the status in the virtual table. The virtual table is filled with 0x4111a9. Note that the address of the virtual table is 0x00000070c. At this time, the first four bytes of the object address 0x0012ff60 are stored in 0x00000070c.

Continue tracing, and the process goes back to the constructor of A. Pay attention to the Code in the bold part again. After returning from the constructor of the base class, in the constructor of, reset the virtual table pointer. The current virtual table pointer is (0x417700 h). Similarly, the: fuction function is called directly when the function is called, and no virtual mechanism is used, in this case, 0x41110e is the address of a: fuction.

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, 33 H
004115a8 mov eax, 0 cccccccch
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 (411140 H)

004115bb mov eax, dword ptr [this]
004115be mov dword ptr [eax], offset a: 'vftable' (417700 H)
{
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


It's actually that simple.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.