1. A function declared with the virtual keyword is called a virtual function, and a virtual function is definitely a member function of a class.
2. A class with a virtual function has a one-dimensional virtual function table called a virtual table. The object of the class has a virtual pointer that points to the beginning of the virtual table. A virtual table corresponds to a class, and a virtual table pointer corresponds to an object.
3. Polymorphism is a multi-interface implementation, is the core of object-oriented. It is divided into the polymorphism of the class and the polymorphism of the function.
4. Multi-state is implemented by virtual function, combined with dynamic binding.
5. A pure virtual function is a virtual function plus = 0.
6. Abstract class refers to a class that includes at least one pure virtual function.
Pure virtual function: virtual void breathe () = 0; abstract Class! This function must be implemented in subclasses! That is, the first name, no content, in the derived class to implement the content!
Let's look at an example first:
#include <iostream.h>
Class Animal
{
Public
void Sleep ()
{
cout<< "Animal Sleep" <<endl;
}
void Breathe()
{
cout<< "Animal Breathe" <<endl;
}
};
Class Fish:public Animal
{
Public
void Breathe()
{
cout<< "Fish Bubble" <<endl;
}
};
void Main ()
{
Fish FH;
Animal *pan=&fh; //implicit type conversion
Pan->breathe ();
}
Note that the virtual function is not defined in the program in example 1-1. Consider the results of program execution in example 1-1?
The answer is output: animal breathe
We first defined a fish class object FH in the main () function, then defined a pointer variable pan to the animal class, assigned the address of the FH to the pointer variable pan, and then called Pan->breathe () using the variable. Many learners often confuse this with C + + polymorphism, thinking that the FH is actually a fish class object, that it should be called the Fish Class Breathe (), the output "fish bubble", and then the result is not the case. Here are two ways to tell the reason.
1, the angle of the compilation
When compiling the C + + compiler, to determine the address of each function called by the object (which requires this function to be a non-virtual function), this is called early binding (early binding), when we assign the address of the fish class FH to the pan, the C + + compiler makes a type conversion, at which point C + + The compiler thinks that the variable pan holds the address of the animal object. When executing pan->breathe () in the main () function, the call is of course the breathe function of the animal object.
2. The angle of the memory model
We give the fish object memory model as shown in:
Figure 1-1 the memory model of fish class objects
When we construct an object of fish class, we first call the constructor of the animal class to construct the object of the animal class, and then call the fish class's constructor to complete the construction of its own part, Thus stitching out a complete fish object. When we convert an object of fish class to a animal type, the object is considered the upper half of the entire memory model of the original object, which is the "memory occupied by the animal object" in Figure 1-1. So when we use a type-converted object Pointer to invoke its method, it is, of course, the method in memory where it is called. Therefore, the output animal breathe, it is logical.
As many students think, in the program in example 1-1, we know that the pan is actually pointing to the fish class object, and we want the result of the output to be the breathe method of the fishes. At this point, it's time for the virtual function to appear.
The result of the preceding output is that the compiler, at compile time, has determined the address of the function called by the object, and it is necessary to use the late binding (late binding) technique to solve this problem. When the compiler uses late binding, it then determines the type of object and the correct calling function at run time. In order for the compiler to use late binding, the virtual keyword is used when declaring a function in a base class (note that this is necessary, and many students simply write many examples of errors without using virtual functions), which we call virtual functions. Once a function is declared as virtual in the base class, the function is virtual in all derived classes and does not need to be explicitly declared as virtual.
Modify the code in example 1-1 below to declare the Breathe () function in the animal class as virtual, as follows:
#include <iostream.h>
Class Animal
{
Public
void Sleep ()
{
cout<< "Animal Sleep" <<endl;
}
virtual void Breathe()
{
cout<< "Animal Breathe" <<endl;
}
};
Class Fish:public Animal
{
Public
void Breathe()
{
cout<< "Fish Bubble" <<endl;
}
};
void Main ()
{
Fish FH;
Animal *pan=&fh;//implicit type conversion
pan->breathe ();
}
You can run the program again and you will find that the result is "fish bubble", which is called the correct function based on the type of object.
So when we declare breathe () as virtual, what happens behind the scenes?
At compile time, the compiler discovers that there are virtual functions in the animal class, at which point the compiler creates a virtual table (that is, vtable) for each class that contains the virtual function, which is a one-dimensional array in which to store the address of each virtual function. For example 1-2, the animal and fish classes both contain a virtual function breathe (), so the compiler will create a virtual table for all two classes (even if there is no virtual function inside the subclass, but there are in the parent class) as shown in the subclass:
How do I locate a virtual table? The compiler also provides a virtual table pointer (that is, vptr) for each class object that points to the virtual table of the class to which the object belongs. When the program is running, initialize the vptr according to the type of the object, so that vptr correctly points to the virtual table of the owning class, so that when the virtual function is called, the correct function can be found. For example 1-2 of the program, because the pan actually points to the object type is fish, so vptr point to the fish class vtable, when called pan->breathe (), according to the function address in the virtual table is the Fish class breathe () function.
It is important that the virtual table pointers be initialized correctly because each object is called by an imaginary function that is indexed by a virtual table pointer. In other words, we are not able to invoke virtual functions until the virtual table pointers are properly initialized. So when, or where, is the virtual table pointer initialized?
The answer is to create the virtual table in the constructor and initialize the virtual table pointer. Remember the order in which constructors are called, when constructing a subclass object, the constructor of the parent class is called, at which point the compiler only "sees" the parent class, does not know if there are successors after it, initializes the virtual table pointer of the parent class object, and the virtual table pointer points to the virtual table of the parent class. When the constructor of a subclass is executed, the virtual table pointer of the subclass object is initialized, pointing to its own virtual table. For example 2-2, when the FH object of the fish class is constructed, the internal virtual table pointer is initialized to a virtual table that points to the fish class. After the type conversion, call Pan->breathe (), since the pan actually points to the object of the fish class, the virtual table pointer inside the object points to the virtual table of the fish class, so the final call is the Breathe () function of the fish class.
Note: For virtual function calls, there is a virtual table pointer inside each object that is initialized to the virtual table of this class. So in a program, no matter how your object type is converted, but the virtual table pointer inside the object is fixed, it is possible to implement dynamic object function calls, which is the principle of C + + polymorphism implementation.
Summary (the base class has virtual functions):
1. Each class has a virtual table.
2. The virtual table can be inherited, if the subclass does not override the virtual function, then the subclass of the virtual table will still have the address of the function, but this address points to the virtual function of the base class implementation. If the base class has 3 virtual functions, then there are three items in the virtual table of the base class (virtual function address), the derived class will have a virtual table, at least three items, if the corresponding virtual function is overridden, then the address in the virtual table will change, pointing to its own virtual function implementation. If a derived class has its own virtual function, the item is added in the virtual table.
3. The virtual function address in the virtual table of the derived class is arranged in the same order as the virtual function address in the virtual table of the base class.
This is the polymorphism of C + +. When the C + + compiler is compiled, it is found that the breathe () function of the animal class is a virtual function, and C + + will use the late binding (late binding) technique. That is, when the compiler does not determine the function of the specific call, but at run time, depending on the type of object (in the program, we pass the address of the Fish class object) to confirm which function is called, this ability is called C + + polymorphism. When we did not add the virtual keyword before the breathe () function, the C + + compiler determined at compile time which function was called, which is called early binding (early binding).
The polymorphism of C + + is implemented by late binding technology.
C + + polymorphism is summed up in a nutshell: By adding the virtual keyword to a function in the base class, overriding the function in a derived class, the runtime will invoke the corresponding function based on the actual type of the object. If the object type is a derived class, the function of the derived class is called, and if the object type is a base class, the function of the base class is called.
A virtual function is defined in a base class in order to not determine the specific behavior of its derived class. Cases:
Define a base class: Class animal//animals. Its function is breathe ()//breathing.
Then define a class fish//fish. Its function is also breathe ()
Define a class Sheep//Sheep again. Its function is also breathe ()
To simplify the code, define Fish,sheep as a derived class for the base class animal.
Fish, however, is not the same as the breathe of sheep, one that breathes through water in water, one that breathes air directly. So the base class cannot determine how to define breathe, so only one virtual breathe is defined in the base class, which is an empty virtual function. This function is defined separately in the subclass. When a program runs, it finds a class, if it has a base class, finds its base class, and finally runs a function in the base class, then it finds the function in the base class that is the virtual identity, and then returns to the subclass for the same name function. Derived classes are also called subclasses. The base class is also called the parent class. This is the creation of virtual functions, and the embodiment of the polymorphism of the Class (breathe).
Polymorphism here refers to the polymorphism of a class.
Function polymorphism refers to a function is defined as a function of a number of different parameters, they are generally present in the header file, when you call this function, for different parameters, you will invoke different functions with the same name. Example: Rect ()//rectangle. Its parameters can be two coordinate points (point,point) or four coordinates (X1,Y1,X2,Y2), which is called function polymorphism and function overloading.
The polymorphism of a class is implemented by means of virtual functions and deferred binding. The polymorphism of a function is an overload of the function.
In general (no virtual functions are involved), when we invoke a function with a pointer/reference, the function being called depends on the type of the pointer/reference. That is, if the pointer/reference is a pointer/reference to the base class object, the method of the base class is called, and if the pointer/reference is a pointer/reference to the derived class object, the method of the derived class is called, of course, if the derived class does not have this method, it will go up to the base class to find the appropriate method These calls are determined during the compilation phase.
When designing to polymorphism, virtual functions and dynamic bindings are used, at which point the call is not determined at compile time but at runtime. Instead of considering the pointer/reference type alone, the type of the pointer/reference object is used to determine the invocation of the function, which function is called based on the address of the function in the virtual table to which the virtual pointer points in the object.
http://hi.baidu.com/microding/item/ab9042d3d13f75efb3f77717
The realization principle of virtual function and polymorphism in C + + learning Research