Looking at C ++ (virtual functions) from the perspective of Assembly)

Source: Internet
Author: User
Tags class manager

 

[Disclaimer: All Rights Reserved. You are welcome to reprint it. Do not use it for commercial purposes. Contact Email: feixiaoxing @ 163.com]

 

 

 

 

Virtual functions are an important part of object-oriented design. The appearance of this function allows us to only use the same interface function and get different generation results. However, some of our friends know why such a result occurs. We can use a piece of code to explain the problem. First, we should first define two basic types: employee and manager. All the friends who have read the previous blog should be somewhat impressed:

 

 

Class employee

{

Public:

Employee (){}

~ Employee (){}

Virtual void print () const {printf ("employee! \ N ");}

};

 

Class manager: public employee

{

Public:

Manager (){}

~ Manager (){}

Void print () const {printf ("manager! \ N ");}

};

Class employee

{

Public:

Employee (){}

~ Employee (){}

Virtual void print () const {printf ("employee! \ N ");}

};

 

Class manager: public employee

{

Public:

Manager (){}

~ Manager (){}

Void print () const {printf ("manager! \ N ");}

};

We can see that the member functions are slightly different from the previous ones. The print function appears virtual before. However, this virtual has played a huge role. It is no exaggeration to say that, without virtual functions, there is basically no design pattern, which cannot reflect the great superiority of the C ++ language in object-oriented design. Let's take a look at how this virtual works?

 

 

76: employee p;

0040128D lea ecx, [ebp-10h]

00401290 call @ ILT + 45 (employee: employee) (00401032)

00401295 mov dword ptr [ebp-4], 0

77: manager m;

0040129C lea ecx, [ebp-14h]

0040129F call @ ILT + 65 (manager: manager) (00401046)

004012A4 mov byte ptr [ebp-4], 1

78: employee * e = & p;

004012A8 lea eax, [ebp-10h]

004012AB mov dword ptr [ebp-18h], eax

79: e-> print ();

004012AE mov ecx, dword ptr [ebp-18h]

004012B1 mov edx, dword ptr [ecx]

004012B3 mov esi, esp

004012B5 mov ecx, dword ptr [ebp-18h]

004012B8 call dword ptr [edx]

004012BA cmp esi, esp

004012BC call _ chkesp (00408870)

80: e = & m;

004012C1 lea eax, [ebp-14h]

004012C4 mov dword ptr [ebp-18h], eax

81: e-> print ();

004012C7 mov ecx, dword ptr [ebp-18h]

004012CA mov edx, dword ptr [ecx]

004012CC mov esi, esp

004012CE mov ecx, dword ptr [ebp-18h]

004012D1 call dword ptr [edx]

004012D3 cmp esi, esp

004012D5 call _ chkesp (00408870)

82 :}

76: employee p;

0040128D lea ecx, [ebp-10h]

00401290 call @ ILT + 45 (employee: employee) (00401032)

00401295 mov dword ptr [ebp-4], 0

77: manager m;

0040129C lea ecx, [ebp-14h]

0040129F call @ ILT + 65 (manager: manager) (00401046)

004012A4 mov byte ptr [ebp-4], 1

78: employee * e = & p;

004012A8 lea eax, [ebp-10h]

004012AB mov dword ptr [ebp-18h], eax

79: e-> print ();

004012AE mov ecx, dword ptr [ebp-18h]

004012B1 mov edx, dword ptr [ecx]

004012B3 mov esi, esp

004012B5 mov ecx, dword ptr [ebp-18h]

004012B8 call dword ptr [edx]

004012BA cmp esi, esp

004012BC call _ chkesp (00408870)

80: e = & m;

004012C1 lea eax, [ebp-14h]

004012C4 mov dword ptr [ebp-18h], eax

81: e-> print ();

004012C7 mov ecx, dword ptr [ebp-18h]

004012CA mov edx, dword ptr [ecx]

004012CC mov esi, esp

004012CE mov ecx, dword ptr [ebp-18h]

004012D1 call dword ptr [edx]

004012D3 cmp esi, esp

004012D5 call _ chkesp (00408870)

82 :}

The above is a piece of code for function calling. The code can be a little longer. But it does not matter. We can describe and understand it one by one according to the number of lines in the code.

 

Row 76: we have created a Variable p of the employee type, which can be seen from the following constructor:

 

Row 77: we have created a variable of the manager type. This can also be seen from the subsequent manager constructor.

 

Row 78: we create a temporary pointer variable e, which saves the address of the Variable p, which is also relatively simple.

 

Row 79: We found that there are 7 compilations in the 79 sentences below. The third, sixth, and seventh clauses are used to balance the stack, and they have nothing to do with our calls. So what is calling edx? The original function call order is as follows: edx-> [ecx]-> [ebp-0x18], do not know if you understand it. The first byte in the memory records a pointer to the print function pointer, that is, edx. Through this edx, we can find out what the content is at The edx address. Then we extracted it and found that the [edx] content is exactly the print function address we are looking. This is equivalent to a secondary addressing process.

 

Row 80: we re-assigned the Temporary Variable e. At this time, e stores the address of Variable m.

 

Row 81: We found that the search process was the same as that of line 79, because the content of edx was different. That is, the pointer pointing to the function pointer has changed.

 

 

 

 

Imagine what will happen to the above Code without this virtual function?

 

 

76: employee p;

0040127D lea ecx, [ebp-10h]

00401280 call @ ILT + 45 (employee: employee) (00401032)

00401285 mov dword ptr [ebp-4], 0

77: manager m;

0040128C lea ecx, [ebp-14h]

0040128F call @ ILT + 65 (manager: manager) (00401046)

00401294 mov byte ptr [ebp-4], 1

78: employee * e = & p;

00401298 lea eax, [ebp-10h]

0040129B mov dword ptr [ebp-18h], eax

79: e-> print ();

0040129E mov ecx, dword ptr [ebp-18h]

004012A1 call @ ILT + 5 (employee: print) (0040100a)

80: e = & m;

004012A6 lea ecx, [ebp-14h]

004012A9 mov dword ptr [ebp-18h], ecx

81: e-> print ();

004012AC mov ecx, dword ptr [ebp-18h]

004012AF call @ ILT + 5 (employee: print) (0040100a)

82 :}

76: employee p;

0040127D lea ecx, [ebp-10h]

00401280 call @ ILT + 45 (employee: employee) (00401032)

00401285 mov dword ptr [ebp-4], 0

77: manager m;

0040128C lea ecx, [ebp-14h]

0040128F call @ ILT + 65 (manager: manager) (00401046)

00401294 mov byte ptr [ebp-4], 1

78: employee * e = & p;

00401298 lea eax, [ebp-10h]

0040129B mov dword ptr [ebp-18h], eax

79: e-> print ();

0040129E mov ecx, dword ptr [ebp-18h]

004012A1 call @ ILT + 5 (employee: print) (0040100a)

80: e = & m;

004012A6 lea ecx, [ebp-14h]

004012A9 mov dword ptr [ebp-18h], ecx

81: e-> print ();

004012AC mov ecx, dword ptr [ebp-18h]

004012AF call @ ILT + 5 (employee: print) (0040100a)

82 :}

Unfortunately, there is no dynamic search process, and all the print functions finally point to the function employee: print. At this time, polymorphism no longer exists.

Related Article

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.