The essence of virtual function __ function

Source: Internet
Author: User
Tags lowercase
In the object-oriented C + + language, virtual functions (virtual function) are a very important concept. Because it fully embodies the object-oriented concept of inheritance and polymorphism of these two characteristics, in the C + + language application is very wide. For example, in Microsoft's MFC class library, you will find that many functions have virtual keywords, that is to say, they are virtual functions.         No wonder some people even call virtual functions the essence of C + + language. So, what is a virtual function, let's take a look at Microsoft's explanation first: A virtual function is a member function that you want to overload in a class, and when you point to an inherited class object with a base class pointer or reference, you call a virtual function that actually invokes the version of the inherited class.                                                                 --excerpt from MSDN         This definition is not very clear. An example is given in MSDN, but its examples do not give a good indication of the problem. We write our own example: #include "stdio.h" #include "conio.h"   class Parent {public:  char data[20];  void Function 1 ();  virtual void Function2 ();   //here declares that Function2 is a virtual function}parent; void Parent::function1 () { printf (' is parent,function1/n ');} void Parent::function2 () { printf ("This is parent,function2/n "); }   class Child:public Parent { void Function1 ();  void Function2 (); void Child::function1 () { printf ("This is child,function1/n");} void Child::function2 () { printf ("This is child,function2/n"); }   int main (int argc, char* argv[]) { parent *p; //defines a base class pointer  if (_getch () = = ' C ')    &n Bsp If you enter a lowercase letter C        p=&child;         Point to inheriting class object  else        p=&parent;     //Otherwise point to base class object P->function1 ();  ///here will directly give the Parent::function1 ()                                      entry address.  p->function2 ();   //note here, which Function2 is executed.  return 0;         compile and run with any version of Visual C + + or Borland C + +, and enter a lowercase letter, which results in the following: this is Parent,fun Ction1 This is Child,function2       why there is the result of the first line. Because we call the function Fuction1 () with a pointer to a Parent class.Although this pointer actually refers to the object of the child class, but the compiler is not aware of this fact (until the runtime, the program can be based on the user's input to determine what the pointer to the object), it can only be called the Parent class function to understand and compile, so we see the first line of results.         So what's the result of the second line? We notice that the Function2 () function is decorated in the base class by the virtual keyword, which means that it is a virtual function. The most critical feature of a virtual function is a "dynamic link", which can determine the object that the pointer points to at run time and automatically call the corresponding function. If we enter a non-C character at any time when running the above program, the result is as follows: This is parent,function1 the This is Parent,function2          Notice the second line, and the result has changed. Only one Function2 () function is called in the program, but it can automatically decide whether to call the Function2 in the base class or the Function2 in the inheriting class according to the user's input, which is the function of the virtual function. We know that in MFC, many classes are required you to inherit, their member functions are many to overload, such as writing MFC applications most commonly used CView::OnDraw (cdc*) functions, you must overload the use. It is defined as a virtual function (in fact, in MFC, OnDraw is not only a virtual function, or pure virtual function), you can ensure that the time is called by the user to write the OnDraw. The important use of virtual functions is evident here.       on the basis of understanding virtual functions, we consider the problem that a base class pointer must know whether the object it points to is a base class or an example of an inherited class in order to "automatically" decide which version should be invoked when a virtual function is invoked. How it is known. Some C + + books mention that this "dynamic" mechanism is achieved through a "vtable", vtable is what. Microsoft describes it in the documentation on COM:         vtable refers to a table of function pointers, as C + + The same as the implementation of the class in vtable points to an interface member function supported by an object.                                                                        --Excerpt from MSDN         Unfortunately, Microsoft has not made the issue clear this time, of course, the above document is originally about COM, and we are concerned about the issue of different.         so vtable is what. Let's take a look at the following experiment:         add a word printf ("%d", sizeof (child)) in the previous example program; Run, and then remove Function2 () before the virtual keyword, and then run, get the result: when Function2 defined as a virtual function, the result is 24, otherwise the result is 20. That is, if Function2 is not a virtual function, an example of a child class occupies only the size of its member variable data array, and if Function2 is a virtual function, the result is more than 4 bytes. We are using 32-bit Visual C + + 6.0, 4 bytes is just a pointer, or the space occupied by an integer.         So what's the effect of this extra four bytes.         Open the previous sample program with Visual C + + and P->function1 () in the main function; A sentence before pressing F9 set breakpoints, press F5 to start debugging, enter a lowercase c, the program stopped to our set breakpoints. Locate the Debug toolbar and press the Disassembly button as shown in the Picture: (Fig.) Csdn on this should be the author's original. But the picture is gone >_<!! Anyway, no matter what the picture is, it's not important either, go on ...         we see the disassembly code. As the above illustration shows, the code generated after the Function1 and Function2 calls are disassembled. Function1 is not a virtual function, so calls to it are only compiled into a call instruction, to the Parent::function1 subroutine, and Function2 is a virtual function, its code to be more complex, we carefully analyze: 45:  & Nbsp;  &nbSp P->function2 ();    004012ca   mov      eax,dword ptr [ebp-4]// EAX is our P pointer 004012cd   mov      edx,dword PTR [eax]//edx Fetch child object header four bytes 004012CF    mov       esi,esp 004012d1   mov        Ecx,dword ptr [ebp-4]//may want to check the stack, regardless of its 004012d4   call        DWORD ptr [EDX]//Note here, a function pointer called the head of a child object 004012d6   cmp       Esi,esp 004012d8   call         __chkesp (004013b0) The most critical sentence here is call DWORD. Ptr[edx],edx is the child object head, as we analyzed before, the child object has 24 bytes, where the member variable occupies 20 bytes, and 4 bytes are unknown. Now, from this assembly code, the 4 byte is probably the function pointer at the beginning of the child object, because the compiler does not know what our member variable data is for, and it is not possible to treat any part of data as a function pointer. So the function pointer jumps over there. We press F10 step into this call command, and then press F11 to follow: 00401032   jmp         Parent:: Function2 (0040BFE0) 00401037   jmp         Parent::P arent (004010D0)    →  0040103c   jmp         Child:: Function2 (00401250) 00401041   jmp         Child::Child ( 004011C0 the cursor stops at the third row, 40103C Place, executes the JMP instructions here, and jumps to the child::function2 position to get the result we see above. This is not the final conclusion, we look at a few lines of code around 40103C, a few lines are all JMP instructions, what is the program structure. A friend with assembly-language programming experience may recall that this is an entry table that holds the jump instructions to several important functions, respectively. Let's go back and take a look at Microsoft's description of vtable: vtable refers to a table of function pointers (like the implementation of classes in C + +), where the pointer in vtable points to a member function of an interface supported by an object. Do not look at the words in parentheses, the backbone of this sentence is: vtable is a function pointer table, point to member functions. It turns out that the top four lines of code are the vtable we're looking for. Now we should have an idea of the principle of virtual function. Each virtual function occupies a table entry in the vtable, preserving an instruction that jumps to its entry address (in effect, it saves its entry address). When an object containing a virtual function (note, not a pointer to an object) is created, it attaches a pointer to the vtable, pointing to the corresponding position in the header. When calling a virtual function, no matter what pointers you use, it first finds the entry address based on vtable and then executes the "Dynamic binder". Instead of simply jumping to a fixed address like a normal function. The above conclusion is only for the Visual C + + 6.0 compiler, for other compilers, the implementation is not exactly the same, but all the same. The GNU C + + compiler on the Linux platform puts a pointer to vtable on the end of the object rather than the head, the famous "Green Corps" magazine wrote., and the vtable only holds the entry address of the virtual function, not the instruction to jump to the virtual function. Specific details, the length of the limit, we are no longer discussed here, we hope that interested friends can continue to study. PS: To sum up, only to pointers and references, the magic of virtual functions can only function.

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.