The principle of C + + virtual function table

Source: Internet
Author: User

The function of virtual function in C + + is mainly to realize the mechanism of polymorphism. In terms of polymorphism, in short, a pointer to the parent type points to an instance of its child class, and then invokes the member function of the actual subclass through a pointer to the parent class. This technique allows the parent class to have a "multiple form" pointer, which is a generic technique. The so-called generic technology, plainly, is trying to use immutable code to implement a mutable algorithm. For example: template technology, RTTI technology, virtual function technology, either try to do at compile time resolution, or try to achieve runtime resolution.

Anyone who understands C + + should know that virtual functions are implemented by a virtual function table (virtual table). Referred to as v-table. In this table, the master is the Address table of the virtual function of a class, which solves the problem of inheritance, overwriting, and guarantees the actual function of the real response. Thus, in an instance of a class with virtual functions, the table is assigned to the memory of this instance, so when we manipulate a subclass with a pointer to the parent class, the virtual function table is important, and it is like a map that indicates the function that should actually be called.

Here is a look at this virtual function table. The C + + compiler should be a pointer to the virtual function table that exists in the first place in the object instance (this is to ensure the highest performance of the virtual function table if there are multiple layers of inheritance or multiple inheritance). This means that we get this virtual function table from the address of the object instance, and then we can iterate over the function pointer and call the corresponding function.

Suppose there is a class like this:

classBase { Public:             Virtual voidF () {cout <<"Base::f"<<Endl;} Virtual voidG () {cout <<"base::g"<<Endl;} Virtual voidH () {cout <<"base::h"<<Endl;} }; 

According to the above, the virtual function table can be obtained by the example of base.

void (*fun) (void);    = NULL;    " virtual function table address: " << (int*) (&b) <<" virtual function table-First function address:" << (int*) * (int*) (&b) << Endl;    = (Fun) * ((int*) * (int*) (&B)); Pfun ();

The actual run-through results are as follows:

virtual function table Address: 0012FED4
virtual function table-First function address: 0044f148
Base::f

Through this example, you can see that by forcing the &b into an int *, get the address of the virtual function table, and then, once again, the address of the first virtual function can be obtained, that is, Base::f (), which in the above program has been verified (the int* forced into the function pointer). With this example, we know that if you want to invoke Base::g () and Base::h (), the code is as follows:

(Fun) * ((int*) * (int*) (&b) +0);  //  (Fun) * ((int*) * (int*) (&B) +1);  //  (Fun) * ((int*) * (int*) (&B) +2);  // base::h ()

Explain:

Note: In the above diagram, I added a node at the end of the virtual function table, which is the end node of the virtual function table, just like the string Terminator "+", which marks the end of the virtual function table. The value of this end flag is different under different compilers. Under Winxp+vs2003, this value is null. And in Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3, this value is if 1, indicating there is also the next virtual function table, if the value is 0, represents the last virtual function table.

The following describes the appearance of the virtual function table when there is no overwrite and overwrite. It is meaningless not to overwrite the virtual function of the parent class. I want to tell the story of the absence of coverage, the main purpose is to give a contrast.

General Inheritance (no virtual function overrides)

Now, let's look at what the virtual function table looks like when inheriting. Suppose you have an inheritance relationship that looks like this:

Note that in this inheritance relationship, subclasses do not overload functions of any parent class. So, in an instance of a derived class, its virtual function table looks like this:

For example: Derive D; The virtual function table is as follows:

You can see the following points:

1) Virtual functions are placed in the table in the order in which they are declared.

2) The virtual function of the parent class precedes the virtual function of the child class.

General inheritance (with virtual function overrides)

Overriding the virtual function of the parent class is a very obvious thing, otherwise the virtual function becomes meaningless. What would it look like if there were virtual functions in the subclass that overloaded the virtual functions of the parent class? Assume that there is an inheritance relationship like the following.

In the design of this class, only one function of the parent class is overwritten: F (). Then, for instances of derived classes, the virtual function table will look like this:

You can see the following points from the table,

1) the covered F () function is placed in the location of the original parent virtual function in the virtual table.

2) functions that are not covered are still.

Thus, for the following program:

New Derive (); b->f ();

The position of the F () of the virtual function table in memory referred to by B has been replaced by the Derive::f () function address, and derive::f () is called when the actual call occurs. This enables polymorphism.

Multiple inheritance (no virtual function overrides)

Next, take a look at the case in multiple inheritance, assuming that there is an inheritance relationship for one of the following classes. Note: The subclass does not have a function that overrides the parent class.

For a virtual function table in a subclass instance, the following looks like this:

can see:

1) Each parent class has its own virtual table.

2) The member function of the subclass is placed in the table of the first parent class. (The so-called first parent class is judged in order of declaration)

This is done in order to resolve pointers to different parent class types to the same child class instance, and to invoke the actual function.

Multiple inheritance (with virtual function overrides)

Let's take a look at the case where virtual function overrides occur. , the F () function of the parent class is overridden in the subclass.

The following is a diagram of a virtual function table in a subclass instance:

As you can see, the position of F () in the three parent virtual function table is replaced with the function pointer of the subclass. This allows the parent class of any static type to point to the subclass and call F () of the subclass. Such as:

*B1 = &*b2 = &*b3 = &D; B1/ /////    b1//////base3::g () 

Security

First, access the subclass's own virtual function through a pointer to the parent type

Subclasses do not have to overload the virtual functions of the parent class as a meaningless thing. Because polymorphism is also based on function overloading. Although we can see in the above figure that there are derive virtual functions in the virtual table of BASE1, it is not possible to use the following statement to invoke the subclass's own virtual function:

New Derive (); B1->f1 ();  // compilation Error

Any attempt to use a parent pointer to call a member function in a subclass that does not overwrite a parent class is considered illegal by the compiler, so that such a program cannot be compiled at all. But at run time, virtual function tables can be accessed by pointers to violate C + + semantics.

Second, the virtual function of accessing non-public

In addition, if the virtual function of the parent class is private or protected, but these non-public virtual functions also exist in the virtual function table, we can also access the virtual function table in the way of accessing these non-public virtual functions, which is very easy to do.

classBase {Private:             Virtual voidF () {cout <<"Base::f"<<Endl;}   }; classDerive: Publicbase{}; typedefvoid(*fun) (void); voidMain () {Derive D; Fun Pfun= (Fun) * ((int*)*(int*) (&AMP;D) +0); Pfun (); }

Virtual function tables can be seen by expanding an instance of the class in the debug state of the VC's IDE environment.

Here is a demo of virtual function table access for multiple inheritance:

#include <iostream>using namespacestd; classBase1 { Public:             Virtual voidF () {cout <<"Base1::f"<<Endl;} Virtual voidG () {cout <<"base1::g"<<Endl;} Virtual voidH () {cout <<"base1::h"<<Endl;}   }; classBase2 { Public:             Virtual voidF () {cout <<"Base2::f"<<Endl;} Virtual voidG () {cout <<"base2::g"<<Endl;} Virtual voidH () {cout <<"base2::h"<<Endl;}   }; classBASE3 { Public:             Virtual voidF () {cout <<"Base3::f"<<Endl;} Virtual voidG () {cout <<"base3::g"<<Endl;} Virtual voidH () {cout <<"base3::h"<<Endl;}     }; classDerive: PublicBASE1, PublicBase2, Publicbase3{ Public:             Virtual voidF () {cout <<"Derive::f"<<Endl;} Virtual voidG1 () {cout <<"DERIVE::G1"<<Endl;}     }; typedefvoid(*fun) (void); intMain () {fun Pfun=NULL;             Derive D; int* * Pvtab = (int* *) &D; Pfun= (fun) pvtab[0][0];               Pfun (); Pfun= (fun) pvtab[0][1];               Pfun (); Pfun= (fun) pvtab[0][2];               Pfun (); //Derive ' s vtablePfun = (fun) pvtab[0][3];               Pfun (); //The tail of the vtablePfun = (fun) pvtab[0][4]; cout<<pFun<<Endl; //Base2 ' s vtable//Pfun = (fun) * ((int*) * (int*) ((int*) &d+1) +0);Pfun = (fun) pvtab[1][0];               Pfun (); Pfun= (fun) pvtab[1][1];               Pfun (); Pfun= (fun) pvtab[1][2];                Pfun (); //The tail of the vtablePfun = (fun) pvtab[1][3]; cout<<pFun<<Endl; //Base3 ' s vtablePfun = (fun) pvtab[2][0];               Pfun (); Pfun= (fun) pvtab[2][1];               Pfun (); Pfun= (fun) pvtab[2][2];                Pfun (); //The tail of the vtablePfun = (fun) pvtab[2][3]; cout<<pFun<<Endl; return 0; }

The principle of C + + virtual function table

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.