C + + virtual functions

Source: Internet
Author: User
Tags class definition

Http://blog.sina.com.cn/s/blog_625ef6610101g9f2.html


Definition: A member function syntax declared in a base class as virtual and redefined in one or more derived classes: The virtual function returns the type function name (parameter table) {function body;} Use :To implement polymorphism, by pointing to a base class pointer to a derived class, accessing the overridden member function in a derived class with the same name the virtual function must be a non-static member function of the base class, and its access rights can be private or protected or public, defining the general form of the virtual function in the class definition of the base class: The Class base class name {.... virtual return value type the function name (parameter list) that will be overloaded in the derived class;};2The function of virtual function is to implement dynamic linking, that is, to select the appropriate member function dynamically during the running phase of the program, after defining the virtual function, the virtual function can be redefined in the derived class of the base class, and the function redefined in the derived class should have the same parameter number and parameter type as the virtual function. To achieve a unified interface, different definition process. If a virtual function is not redefined in a derived class, it inherits the virtual function of its base class. When the program discovers the key word in front of the virtual function name virtual, it will automatically be used as a dynamic binder, that is, when the program is run, dynamically select the appropriate member functions. Virtual functions are a representation of C + + polymorphism. For example, if a subclass inherits a function (method) of the parent class, and we point the pointer of the parent class to the subclass, then the function (method) of the parent class must be set to virtual (virtual function). ([2010.10.28] Note: The downlink semantics are easy to produce an understanding deviation, the actual effect should be: if exist: Derive1, Derive2 and their own virtual function func () when accessing an instance of a derived class Derive1, A pointer or reference that uses its base class base and its own type Derive1, or a subsequent derived class that is statically converted Derive2, can access the Func () implemented by DERIVE1. Dynamic-linking specifies that a virtual function can only be called by a pointer to a base class or a reference to a base class object, in the format: 1, pointer to a base class variable name, virtual function name (argument table) 2, reference name of the base class object. virtual function name (argument table) using virtual function, we can flexibly dynamic binding, of course, at the cost of a certain cost. If the parent class function (method) is not necessary or impossible to implement, completely dependent on the subclass to implement, you can set this function (method) to the virtual function name = 0 We call such a function (method) pure virtual functions. If a class contains a pure virtual function, this class is called an abstract class.3ExampleExample#includeusing namespace Std;class cshape{public:void setcolor (int color) {m_ncolor=color;} virtual void Display (void) {cout<< "Cshape" <<endl;} Private:int M_ncolor;}; Class crectangle:public cshape{public:virtual void Display (void) {cout<< "Crectangle" <<endl;}; Class Ctriangle:public Cshape {virtual void Display (void) {cout<< "Ctriangle" <<endl;}}; Class Cellipse:p ublic Cshape {public:virtual void Display (void) {cout<< "Cellipse" <<endl;}}; void Main () {Cshape obshape; Cellipse Obellipse; Ctriangle Obtriangle; Crectangle Obrectangle; Cshape * pshape[4]= {&obShape,&obEllipse,&obTriangle,& obrectangle};for (int i= 0; i< 4; i++) pshape[i ]->display ();} This program running result: Cshapecellipsectrianglecrectangle if the Cshape class inside virtual void Display (void) When virtual is removed, the result is different: CshapecshapecshapecshapeconditionsTherefore, from the above program analysis, the realization of dynamic linking requires three conditions: 1, the dynamic-linked behavior must be defined as the virtual function of the class. 2. There is a subtype relationship between classes, which generally manifests as a class that derives from another class public. 3, you must first use the base class pointer to the object of the subtype, and then directly or indirectly use the base class pointer to call the virtual function.4of C + +The following is an understanding of the virtual functions of C + +.One, defineSimply put, those member functions that are modified by the virtual keyword are virtual functions. The function of virtual function, the use of professional terminology to explain is to achieve polymorphism (polymorphism), polymorphism is the interface and implementation of the separation, with the image of the language is to achieve a common approach, but because of individual differences and adopt different strategies. Let's look at a simple code class a{public:void print () {cout<< "This is A" <<endl;}}; Class B:public A{public:void print () {cout<< "This is B" <<endl;}}; int main () {///in order to make it easier to distinguish later, my main () code is called main1a A; B b;a.print (); B.print ();} With the print () interface of Class A and class B, we can see that these two classes adopt different strategies depending on the individual differences, and the output is what we expect, respectively, that is a and this is B. But is this really polymorphism? No, polymorphism There is also a key point is everything with a pointer to the base class or reference to manipulate the object. Now change the code at main (). int main () {//main2a A; b b; A * p1=&a; A * P2=&b;p1->print ();p 2->print ();} Run a look at the results, Yo Ah, suddenly looking back, the result is two A. The problem is, P2 clearly points to the object of Class B but is called the print () function of class A, which is not the result we expect, then we need to solve this problem to use the virtual function class a{public:virtual void print () {cout << "This is A" &LT;&LT;ENDL;} Now it's a virtual function.};class b:public a{public:void Print () {cout<< "This is B" &LT;&LT;ENDL;}//Do you need to add the keyword virtual to the front? There is no doubt that the member function print () of Class A has become a virtual function, so is the print () of class B a virtual function? The answer is yes, we simply set the member function of the base class to virtual, and the corresponding function of its derived class automatically becomes a virtual function. So, CLAThe print () of SS B also becomes a virtual function. If you need to modify the virtual keyword before the corresponding function of the derived class, it is your own problem. Now rerun the MAIN2 code so that the result of the output will be this is a and this is B. Now to digest, I make a simple summary, the pointer to the base class when manipulating its Polymorphic class object, according to the different class object, the corresponding function is called, this function is a virtual function.two, realize(If you have not read the Inside the C + + Object Model, but are eager to know, then you should start from here) how does a virtual function invoke its corresponding function depending on the object? Now we're going to parse the virtual function. We first define two classes class a{//Virtual function sample code public:virtual void Fun () {Cout<<1<<endl;} virtual void fun2 () {cout<<2<<endl;}}; Class B:public A{public:void Fun () {Cout<<3<<endl;} void Fun2 () {cout<<4<<endl;}}; Because there are virtual functions in these two classes, the compiler inserts data for them that you do not know and creates a table for them respectively. That data is called the vptr pointer, pointing to that table. The table is called VTBL, each class has its own VTBL,VTBL function is to save the address of the virtual function in their own class, we can see the VTBL image as an array, each element of this array is the address of the virtual function, see the figure
From the left graph, you can see that these two vtbl are both Class A and Class B services respectively. Now that we have this model, let's analyze the following code a *p=new a;p->fun (), without a doubt, call the A::fun (), but how is a::fun () called? Does it jump directly to the code of the function like a normal function? No, in fact, the first is to take out the value of vptr, this value is the address of VTBL, and then according to this value came to vtbl here, because the function called A::fun () is the first virtual function, so take out the value of the first slot in VTBL, this value is the address of A::fun (), Finally, this function is called. Now we can see that, as long as the vptr is different, pointing to the VTBL is different, and different vtbl loaded with the corresponding class of virtual function address, so that virtual function can complete its task. And for Class A and Class B, where are their vptr pointers stored? In fact, this pointer is placed in their respective instance object. Since both Class A and Class B have no data members, there is only one vptr pointer in their instance object. From the above analysis, let's now implement a piece of code to describe this simple model of a class with virtual functions. #includeusing namespace std;//Add the above "virtual function sample code" here int main () {void (*fun) (A *); A *p=new b;long lvptraddr;memcpy (&lvptraddr,p,4) memcpy (&fun,reinterpret_cast (LVPTRADDR), 4); Fun (p);d elete P;system ("Pause");} Compile with VC or dev-c++ to see if the result is output 3, if not, then the sun must come out from the West tomorrow. Now start analyzing void (*fun) (A *) step-by-step. This paragraph defines a function pointer named fun, and there is a * type parameter, which is later used to hold the function address taken out of VTBL a * p=new B; New B is to memory (memory divided into 5 extents: global namespace, free store, register, code space, stack) The free store requests the address of a memory unit and implicitly saves it in a pointer. Then assign this address to the type a pointer p. Long lvptraddr; This long variable is later used to hold the value of Vptr memcpy (&lvptraddr,p,4); As I said before, they only have vptr pointers in their instance objects., so we will be assured that the P refers to the 4bytes memory of the contents of the copy to Lvptraddr, so the 4bytes content copied out is the value of vptr, that is, VTBL address now has VTBL address, So we'll take out the contents of VTBL's first slot now memcpy (&fun,reinterpret_cast (LVPTRADDR), 4); Take out the contents of the first slot in the VTBL and store it in the function pointer fun. Note that the lvptraddr inside is the address of the VTBL, but LVPTRADDR is not a pointer, so we have to turn it into a pointer type fun (p); Here called the function that was taken out of the address of the function, that is called b::fun () This function, maybe you found out why there is a parameter p, in fact, the class member function call, there will be a this pointer, this is the this pointer, just in the general call of the compiler to automatically handle it for you , and here you need to handle it yourself. Delete p; Free space that is directed by P; system ("pause"); The screen pauses; what if I call B::fun2 ()? Then take out the value in the second slot of the VTBL. memcpy (&fun,reinterpret_cast (lvptraddr+4), 4); Why add 4? Because the length of a pointer is 4bytes, add 4. or memcpy (&fun,reinterpret_cast (LVPTRADDR) +1,4); This is more in line with the use of the array, because LVPTRADDR is turned into a long* type, so +1 is the length of the backward sizeof (long) Three, code example #includeusing namespace Std;class a{//virtual function sample code 2public:virtual void Fun () {cout<< "A::fun" &LT;&LT;ENDL;} virtual void fun2 () {cout<< "A::fun2" <<endl;}}; Class B:public A{public:void Fun () {cout<< "B::fun" &LT;&LT;ENDL;} void Fun2 () {cout<< "b::fun2" <<endl;}}; end//virtual Function Example code 2int main () {void (A::* Fun) ();//define a function pointer a *p=new b;fun=&a::fun; (P->*fun) (); fun = &A::fun2; ( P->*fun) ();d elete p;system ("pause"); Can you estimate the output? If you estimate the result is a::fun and a::fun2, hehe, congratulations XI, you trap. In fact, the real result is b::fun and b::fun2, if you can not get through, then look down. Give a hint, &a::fun and &a::fun2 really get the address of the virtual function? First we go back to the second part, we get a "general" method to obtain the virtual function address by the segment implementation Code #includeusing namespace std;//Add the above "virtual function example code 2" here void Callvirtualfun (void* Pthis,int index=0) {void (*funptr) (void*); long lvptraddr;memcpy (&lvptraddr,pthis,4); memcpy (&funptr, Reinterpret_cast (LVPTRADDR) +index,4); Funptr (pThis); Call}int Main () {a * p=new B; Callvirtualfun (P); Call virtual function P->fun () callvirtualfun (p,1);//Call virtual function p->fun2 () system ("Pause");}CallvirtualfunNow we have a "generic" Callvirtualfun method. What is the connection between this generic method and the code at the beginning of Part three? Contact is very large. Since A::fun () and a::fun2 () are virtual functions, &a::fun and &a::fun2 obtain not the address of the function, but rather a section of code that indirectly obtains the address of a virtual function, We visualize this piece of code as the Callvirtualfun. At compile time, the compiler will provide code similar to Callvirtualfun, when you call the virtual function, is actually called the section of the code similar to Callvirtualfun, through this code, to obtain the virtual function address, the last Call virtual function, this really guarantees the polymorphism. At the same time, we all say that the virtual function is inefficient, the reason is that before the virtual function is called, the code to obtain the virtual function address is also called.5Additional InformationLimits for defining virtual functions: (1) Non-class member functions cannot be defined as virtual functions, and static member functions and constructors in the member functions of a class cannot be defined as virtual functions, but destructors can be defined as virtual functions. In fact, good programmers often define the destructor of a base class as a virtual function. Because, after defining a destructor for a base class as a virtual function, the system invokes the destructor of the corresponding class when it deletes a pointer to the object defined by the derived class using Delete. Instead of defining a destructor as a virtual function, only the destructor of the base class is called. (2) You only need to use the keyword "virtual" in the class body of the declaring function to declare the function as a virtual function, and you do not need to use the keyword "virtual" when defining the function. (3) When a member function in a base class is declared as a virtual function, the function with the same name in the derived class automatically becomes a virtual function. (4) If a member function is declared as a virtual function, a non-virtual function that has the same name as the member function and returns a value, the number of arguments, and the same type cannot appear in the class. This same name function cannot be present in a derived class that is a base class of this class. A virtual function is associated with polymorphism, and polymorphism is associated with inheritance. So this article is on the inheritance level of the fuss. Without inheritance, nothing is to be talked about.6Final DescriptionThe code in this article can be compiled with VC6 and dev-c++4.9.8.0 and run without problems. The other compiler little brother is not sure. The analogy method can only be regarded as the model, because the different compiler's bottom-up implementation is different. For example, the dev-c++ gcc is passed as a parameter by pressing the stack, while the VC compiler is saved in ECX by taking out the address. So these analogy methods cannot be used as concrete implementations.
#include <iostream>using namespace::std;//common function rewrite class father{private:    int a;public://plus virtual is virtual function   virtual void jump (void)    {    cout<< ' jump 1.3M ';    };        void Sing (void)    {        cout<< "sing";    }    virtual void hehhe (void)    {    cout<< "hehe";    }    With Virtul Plus 8 bytes};class son:public father{public:    void jump (void)    {    cout<< ' jump 2m ';    };};/ /virtual function rewrite//virtual function-table Virtul tableint main (int argc, const char * argv[]) {    //Insert code    here ... Std::cout << "Hello, world!\n";        Father F;    F.jump ();    Son s;    S.jump ();        Father * Fp=new son;    Fp->jump ();//The method that prints the parent class    //compiler decides who to call, compiler only recognize type, compare OC OC All methods are virtual methods        father &fr=s;    Fr.jump ();        If the method of the parent class adds the Virtul keyword, the method of the subclass is called    return 0;}



C + + virtual functions

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.