C ++ code analysis

Source: Internet
Author: User

C ++ virtual functions are part of polymorphism. polymorphism refers to the function that is called during runtime. The following is an example of pure virtual functions:
# Include "stdafx. h"
Class Test {
Public:
Test (){
Printf ("Test: Test \ n ");
}
Virtual ~ Test (){
Printf ("Virtual ~ Test () \ n ");
}
Virtual void prointer () = 0;
Virtual void pointf () = 0;
};
Class TestA: public Test {
Public:
TestA (){
Printf ("TestA: TestA \ n ");
}
Virtual ~ TestA (){
Printf ("TestA: TestA \ n ");
}
Virtual void prointer (){
Printf ("Derive Class TestA: Pointer \ n ");
}
Virtual void pointf (){
Printf ("Derive Class TestA: Pointf \ n ");
}
};
Int _ tmain (int argc, _ TCHAR * argv []) {
TestA * pTest = new TestA;
PTest-> pointf ();
PTest-> prointer ();
Delete pTest;
Return 0;
}
This Code defines an abstract class and a derived class. An abstract class cannot create its own object, but it can indirectly create its own object from the derived class to form the condition of pure virtual function:
1. A virtual function must exist in a class.
2. Add a = 0 after the virtual function, which is a pure virtual function.
All pure virtual functions of the abstract base class must be overwritten by the virtual functions defined by the derived class. Otherwise, the derived class is also an abstract base class and cannot create its own object. First, let's look at the Test class, because the Test class cannot create its own object, I use the TestA class to parse the call process. We can regard the Test class as an address. There are some pointers in this address, just the address of the function. If the address of the Test class is 0x401000, in this address, the first one is the virtual constructor, which is called when class objects are released, and the second one is gone, because we only define one destructor and one constructor in the Test class, the constructor will be pushed to Main by the compiler from the class during compilation, check the disassembly code:
00401091 |. 6A 04 PUSH 4
00401093 |. E8 68000000 CALL <JMP. & MSVCR90.operator new>
00401098 |. 8BF0 mov esi, EAX
0040109A |. 83C4 04 add esp, 4
0040109D |. 85F6 test esi, ESI
0040366f |. 74 27 je short 004010C8
Here is TestA * pTest = new TestA. From this code, we can see that new is always called successfully, because CALL <JMP. the return value after & MSVCR90.operator new> is compared to whether it is equal to 0. Although this is not our code, the compiler is enough to determine whether new will be called successfully in any case, if CALL <JMP. if the return value of & MSVCR90.operator new> is 0, constructor will be skipped, and constructor will be called by the program. If it is not called, this is the opposite of the C ++ constructor statement. Therefore, the memory allocated by the new operator will be successful. Let's take a look at the following code:
004010A1 |. 57 PUSH EDI
004010A2 |. 8B3D B0204000 mov edi, dword ptr ds: [<& MSVCR90.printf>]; msvcr90.printf
004010A8 |. 68 0C214000 PUSH 0040210C;/format = "Test: Test"
004010AD |. C706 7C214000 mov dword ptr ds: [ESI], 0040217C; |
004010B3 |. FFD7 call edi; \ printf
004010B5 |. 68 2C214000 PUSH 0040212C; ASCII "TestA: TestA"
004010BA |. C706 8C214000 mov dword ptr ds: [ESI], 0040218C
004010C0 |. FFD7 CALL EDI
This code is obviously called by the constructor of two classes, so two addresses are passed to ESI. Let's take a look at the class content of this address. Let's take a look at it in the data window, select the address format as the display format.
0040217C 00401000 this is the content of this address, a Code address
C ++ constructor. 00401000 the first address points to the following address.
00401000. 56 PUSH ESI
00401001. 8BF1 mov esi, ECX
00401003. 68 18214000 PUSH 00402118;/format = "Virtual ~ Test ()"
00401008. C706 7C214000 mov dword ptr ds: [ESI], 0040217C; |
0040100E. FF15 B0204000 call dword ptr ds: [<& MSVCR90.printf>]; \ printf
This is obviously a function, so when a class has a virtual destructor, the address of this virtual destructor will be placed at the beginning of the class pointer, here, we put the pointer to the Test address in ESI, and then determine whether to call the delete Operator Based on ESP + 8. These are automatically added by the compiler. This is the case of the compiler, I haven't studied that technology yet
00401014. 83C4 04 add esp, 4
00401017. F64424 08 01 test byte ptr ss: [ESP + 8], 1
0040101C. 74 09 je short 00401027
0040101E. 56 PUSH ESI
0040101F. E8 D6000000 CALL <JMP. & MSVCR90.operator delete>
00401024. 83C4 04 add esp, 4
00401027> 8BC6 mov eax, ESI
00401029. 5E POP ESI
0040102A. C2 0400 RETN 4
Continue with the above constructor. After the class constructor is called from top to bottom, the address of Test and TestA is passed to ESI. We declare the object of TestA, so the last address is TestA. Check the calling process of the disassembly code.
004010C2 |. 83C4 08 add esp, 8
004010C5 |. 5F POP EDI
004010C6 |. EB 02 jmp short 004010CA
004010C8 |> 33F6 xor esi, ESI
004010CA |> 8B06 mov eax, dword ptr ds: [ESI];
004010CC |. 8B50 08 mov edx, dword ptr ds: [EAX + 8]
004010CF |. 8BCE mov ecx, ESI
004010D1 |. FFD2 CALL EDX
Here, ESI points to the starting address of the TestA class. After uploading the starting address to EAX, it places a function address in this class into EDX. the TestA class has four functions, the constructor was called externally, that is, Main, so there are only three addresses left in it. We know that if a class has a virtual destructor, the first address points to the address of the virtual destructor, and EAX + 8 is called.
PTest-> pointf (); As for why, let's think about it. mov ecx and ESI use ECX to ensure stack balance.
004010D3 |. 8B06 mov eax, dword ptr ds: [ESI]; C ++ constructor. 0040218C
004010D5 |. 8B50 04 mov edx, dword ptr ds: [EAX + 4]
004010D8 |. 8BCE mov ecx, ESI
004010DA |. FFD2 CALL EDX
PTest-> prointer () is called here, because we decide which function to call based on the class address.
004010DC |. 8B06 mov eax, dword ptr ds: [ESI]
004010DE |. 8B10 mov edx, dword ptr ds: [EAX]; C ++ constructor. 00401050
004010E0 |. 6A 01 PUSH 1
004010E2 |. 8BCE mov ecx, ESI
004010E4 |. FFD2 CALL EDX
Here we call the virtual constructor of the TestA class, that is, the first pointer to the address of the current class. Let's trace it and take a look. The following is the disassembly code:
00401050. 56 PUSH ESI
00401051. 57 PUSH EDI
00401052. 8B3D B0204000 mov edi, dword ptr ds: [<& MSVCR90.printf>]; msvcr90.printf
00401058. 8BF1 mov esi, ECX
0040105A. 68 2C214000 PUSH 0040212C;/format = "TestA: TestA"
0040105F. C706 8C214000 mov dword ptr ds: [ESI], 0040218C; |
00401065. FFD7 call edi; \ printf
00401067. 68 18214000 PUSH 00402118; ASCII "Virtual ~ Test ()"
00401_c. C706 7C214000 mov dword ptr ds: [ESI], 0040217C
00401072. FFD7 CALL EDI
00401074. 83C4 08 add esp, 8
00401077. F64424 0C 01 test byte ptr ss: [ESP + C], 1
004020.c. 74 09 je short 00401087
004020.e. 56 PUSH ESI
004020.f. E8 76000000 CALL <JMP. & MSVCR90.operator delete>
00401084. 83C4 04 add esp, 4
00401087> 5F POP EDI
00401088. 8BC6 mov eax, ESI
0040108A. 5E POP ESI
004020. B. C2 0400 RETN 4
Here we call two virtual destructor. Why is it called first ~ TestA, instead of calling ~ Test, because we define these two destructor as virtual functions. The virtual functions decide who to call at runtime. After we call the member functions of TestA, the Destructor is automatically called. Therefore, after TestA is complete, it calls its own destructor to release the latest allocated memory. Therefore, call TestA's constructor first, call the Test constructor again, which is why the Destructor is declared as a virtual function,
After two virtual destructor are called, The delete pointer is used to delete the address allocated by new. The analysis is complete.
Summary:
When we define a class with a virtual function, the virtual function of this class will be placed in an address table, and this address table will be placed in the class entry, when we call a class, we use the class entry to call the virtual functions in it. This proves the polymorphism mechanism of the virtual functions with the same name in C ++.
It is not easy to speak. If there is any error, please point it out. Thank you!


Author: "technology changes the world"

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.