C ++ virtual function table learning notes

Source: Internet
Author: User

A. Basic Knowledge


The virtual function table of the class is a continuous memory. Each memory unit records the location of a JMP command.

 


Note that the compiler will create a virtual function table for each class with virtual functions, which will be shared by all objects in the class. Each virtual member of the class occupies a row in the virtual function table. If there are n virtual functions in the class, the virtual function table will have n * 4 bytes.
  

 


Virtual Function
Table
. V-table for short. In this table, it is mainly an address table of class virtual functions. This table solves the inheritance and overwrite issues and ensures that it truly reflects the actual functions. This
Example: In an instance with a virtual function class, this table is allocated to the memory of this instance. Therefore, when the parent class pointer is used to operate a subclass, this virtual function table is very important. It is like a local
The figure is the same, indicating the function to be called.
  

 


The compiler should ensure that the pointer of the virtual function table exists at the top of the object instance (this is to ensure the highest performance of the obtained virtual function table-if there is multi-layer inheritance or multi-layer inheritance) ). This means that the virtual function table can be obtained through the address of the object instance, and then the function pointer can be traversed and the corresponding function can be called.

 


The role of a virtual function is to implement dynamic association, that is, to dynamically select an appropriate member function in the running stage of the program. After defining a virtual function, you can redefine the virtual function in the derived class of the base class (the form is also:

 


Virtual

Function return value type virtual function name (parameter table) {function body
})

 


The new function in the derived class should have the same number of parameters and type as the virtual function. To implement unified interfaces and different definition processes. If the virtual function is not redefined in the derived class, it inherits the virtual function of its base class. When the program finds the keyword virtual before the virtual function name, it automatically uses it as a dynamic concatenation processing, that is, it dynamically selects the appropriate member function when the program is running.

 

 

  Three conditions are required for dynamic Association:

1. the behavior that requires dynamic association must be defined as a virtual function of the Public attribute of the class.

2. There is a Subtype Relationship between classes. Generally, a class is derived from another class.

3. You must first use a base class pointer to point to a child type object, and then directly or indirectly use a base class pointer to call a virtual function.

 

  Limits on defining virtual functions:

 
(1) Non-class member functions cannot be defined as virtual functions, and static member functions and constructors cannot be defined as virtual functions in class member functions, however, you can define the Destructor as a virtual function. In fact, excellent programs
Members often define the destructor of the base class as virtual functions. Because after you define the destructor of the base class as a virtual function, the system calls the corresponding
Class destructor. Instead of defining a destructor as a virtual function, only the basic class's destructor are called.

(2) You only need to use the keyword "virtual" in the class body of the declared function to declare the function as a virtual function, but do not need to use the keyword "virtual" when defining the function ".

(3) If a member function is declared as a virtual function, a non-virtual function with the same name and return value, number of parameters, and parameter type cannot appear in this class. In a derived class of the base class, such non-virtual functions with the same name and return values as the number of parameters and parameter type functions cannot appear.

 

B. Feel the existence of the virtual function table"

 


First, paste a piece of code to show us how she exists! (Windows 7 + vs2010 passed the test)

//////////////////////////////////////// /// // <Br/> // virtualtable. CPP virtual function learning notes (feel its existence) <br/> // compiling environment: win7 + vs2010 <br/> // by Koma 2010-08-29 <br/> # include "stdafx. H "<br/> # include <iostream> <br/> using namespace STD; <br/> class basenovtable <br/>{< br/> public: <br/> void retriable () {}; <br/>}; <br/> class basevirtualtable <br/>{< br/> public: <br/> virtual void retriable () {}; <br/>}; <br/> int _ tmain (INT argc, _ tchar * argv []) <br/> {<br/> basenovtable BS; <br/> basevirtualtable BVT; <br/> cout <sizeof (BS) <Endl; <br/> cout <sizeof (BVT) <Endl; <br/> return 0; <br/>}< br/> // end of virtualtable. CPP <br/> /////////////////////////////////// /// // <br/>

 


The running result is as follows:

 

If you really want to know why, please read the following knowledge carefully! (If you are familiar with assembly and pointer, the following will be easier to understand ......)

 

C. in-depth exploration of the C ++ virtual function table



 

General inheritance (no virtual function overload)


Next, let's take a look at what the virtual function table looks like during inheritance. Assume there is an inheritance relationship as follows:

 

Figure 2

 

Note that in this inheritance relationship, the subclass does not overload any function of the parent class. In the instance of the derived class, the virtual function table is as follows:

The following table lists the virtual functions of instance: derive D:

 

Figure 3

 

We can see the following points:

 

1) virtual functions are stored in the table in the declared order.

2) the virtual function of the parent class is prior to the virtual function of the subclass.

 

I believe that you can write a program for verification by referring to the previous program.

 

General inheritance (with overload of virtual functions)


It is obvious to overload the virtual functions of the parent class. Otherwise, the virtual functions become meaningless. Next, let's take a look at what it will look like if there is a virtual function in the subclass that reloads the virtual function of the parent class? Suppose we have the following inheritance relationship.

 

Figure 4

 

In order to let everyone see the inherited effect, in this class design, I only reload a function of the parent class: F (). Then, the virtual function table of the instance of the derived class will look like the following:

 

Figure 5

 

We can see the following points from the table,

 

1) The overloaded F () function is placed at the original parent class virtual function in the virtual table.

2) functions that are not overloaded still exist.

 

In this way, we can see the following program,

  Base *b = new Derive();
b->f();  

 

The F () Position of the virtual function table in memory referred to by B has been replaced by the derive: F () function address, so when the actual call occurs, it is derive :: F () is called. This achieves polymorphism.

 

Multi-inheritance (no virtual function overload)


Next, let's take a look at the multi-inheritance situation. Suppose there is an inheritance relationship of the following class. Note: The subclass does not overload the function of the complex class.

 

Figure 6

 

The following figure shows the virtual function table in the subclass instance:

 

Figure 7

 

We can see that:

 

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 first parent class is determined in the Declaration Order)

In this way, the actual function can be called to resolve the pointer of different parent classes pointing to the same subclass instance.

 

Multiple inheritance (with virtual function overloading)

 

Next, let's take a look at the case of virtual function overloading.

 

.

Figure 8

 

The following figure shows the virtual function table in the subclass instance:

 

Figure 9

 

We can see that the F () position in the three parent class virtual function tables is replaced with the function pointer of the subclass. In this way, we can direct any static parent class to the subclass and call the F () of the subclass. For example:

 

Derive d;
Base1 *b1 = &d;
Base2 *b2 = &d;
Base3 *b3 = &d;
b1->f(); //Derive::f()
b2->f(); //Derive::f()
b3->f(); //Derive::f()
b1->g(); //Base1::g()
b2->g(); //Base2::g()
b3->g(); //Base3::g()

 

Security

 

Every time I write a C ++ article, I always have to criticize C ++. This article is no exception. As described above, I believe we have a more detailed understanding of the virtual function table. The water can carry boat, but also the boat. Next, let's take a look at what we can do with a virtual function table.

 

1. Use a pointer of the parent type to access the virtual function of the subclass.


We know that it is meaningless for the subclass to overload the virtual function of the parent class. Because polymorphism is also based on function overloading. Although we can see in the figure above that the virtual table of base1 has a virtual function of derive, we cannot use the following statement to call its own virtual function of the subclass:

 

Base1 * b1 = new derive ();
B1-> F1 (); // compilation Error

 

Any attempt to use a parent class pointer to call a member function of the Child class that does not overload the parent class will be deemed invalid by the compiler. Therefore, such a program cannot be compiled. However, during runtime, we can access the virtual function table through pointers to violate the C ++ semantics. (I believe you can do this by reading the code in the appendix below)

 

2. Access non-public virtual functions


In addition, if the parent class's virtual functions are private or protected, but these non-public virtual functions will also exist in the virtual function table, we can also access these non-public virtual functions by accessing the virtual function table, which is easy to achieve.

For example:

 

class Base {
private:
virtual void f() { cout << "Base::f" << endl; }
};
class Derive : public Base{
};
typedef void(*Fun)(void);
void main() {
Derive d;
Fun  pFun = (Fun)*((int*)*(int*)(&d)+0);
pFun();
}

 

Conclusion

 

C ++ is a magic language. For programmers, we can never find out what we are doing with this language. To be familiar with this language, we must understand the things in C ++ and the dangerous things in C ++. Otherwise, this is a programming language for throwing stones at your own feet.

 

I 'd like to introduce myself before the end of this article. I have been engaged in software R & D for more than ten years. Currently, I am a software development technical director. I am mainly engaged in UNIX, C, and C ++. I prefer network technologies.
Technology, such as distributed computing, grid computing, P2P, Ajax, and other Internet-related things. Management is good at team building, technical trend analysis, and project management.

 

Appendix 1: view the virtual function table in VC


We can expand the class instance in the debug state of the vc ide environment to see the virtual function table (not very complete ).

 

Figure 10

 

Appendix 2: Routine


The following is a routine for accessing multiple inherited virtual function tables:

# Include <iostream> using namespace STD; Class base1 {public: Virtual void F () {cout <"base1: F" <Endl;} virtual void g () {cout <"base1: G" <Endl;} virtual void H () {cout <"base1: H" <Endl ;}}; class base2 {public: Virtual void F () {cout <"base2: F" <Endl;} virtual void g () {cout <"base2 :: G "<Endl;} virtual void H () {cout <" base2: H "<Endl ;}}; class base3 {public: Virtual void F () {cout <"base3: F" <Endl;} virtual void g () {cout <"base3: G" <Endl;} virtual void H () {cout <"base3: H" <Endl ;}}; class derive: Public base1, public base2, public base3 {public: Virtual void F () {cout <"Driver: F" <Endl;} virtual void G1 () {cout <"Driver: G1" <Endl ;}}; typedef void (* Fun) (void); int main () {fun pfun = NULL; derive D; int ** pvtab = (INT **) & D; // base1's vtable // pfun = (fun) * (int *) & D + 0) + 0 ); pfun = (fun) pvtab [0] [0]; pfun (); // pfun = (fun) * (int *) & D + 0) + 1); pfun = (fun) pvtab [0] [1]; pfun (); // pfun = (fun) * (int *) * (int *) & D + 0) + 2); pfun = (fun) pvtab [0] [2]; pfun (); // derive's vtable // pfun = (fun) * (int *) & D + 0) + 3 ); pfun = (fun) pvtab [0] [3]; pfun (); // the tail of the vtablepfun = (fun) pvtab [0] [4]; cout <pfun <Endl; // base2's vtable // pfun = (fun) * (int *) & D + 1) + 0); pfun = (fun) pvtab [1] [0]; pfun (); // pfun = (fun) * (int *) * (int *) & D + 1) + 1); 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 vtable // pfun = (fun) * (int *) & D + 1) + 0); pfun = (fun) pvtab [2] [0]; pfun (); // pfun = (fun) * (int *) * (int *) & D + 1) + 1); 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 ;}

(References:51cto,Big test)

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.