What is polymorphic
The literal understanding is the meaning of multiple forms. The term polymorphic is originally derived from the Greek language, meaning "multiple forms", meaning that there are many forms or forms of the situation, in the C + + language, polymorphic has a broader meaning. In C + + primer, multiple types with inheritance are referred to as polymorphic types, because we can use these types of "multiple forms" without worrying about their differences. The Baidu encyclopedia mentions that in object-oriented languages, many different implementations of interfaces are polymorphic. Referring to the Charlie Calverts description of polymorphism--polymorphism is a technique that allows you to set a parent object to be equal to one or more of his sub-objects, after which the parent object can operate differently depending on the attributes of the child object currently assigned to it. To put it simply, it is a sentence: A pointer to the parent class type is allowed to be assigned a pointer to the child class type. Polymorphism is implemented in Object Pascal and C + + through virtual functions.
Only from the concept of the description is not a clear understanding of it, the following we will be specific analysis.
1. Object type
The type of object described here can be illustrated by the following diagram: We use code to illustrate
1 class Derived1:public Base
2 {};
3 class Derived2:public Base
4 {}:
5 int main()
6 {
7 Derived1* p1 = new Derived1;
8 Base = p1;
9 Derived2* p2 = new Derived1;
10 Base = p2;
11 return = p2
12 }
A static type is always known at compile time, is the type of the variable declaration or the type generated by the expression, and the dynamic type is the type of the object in memory represented by the variable or expression. Dynamic types are not known until run time.
2. Static polymorphism and dynamic polymorphism
The difference between static polymorphism and dynamic polymorphism is actually illustrated by the following diagram:
Static polymorphism
Static polymorphism is also known as static or early binding. When the compiler completes during compilation, the compiler can infer that the function is called if it is called by the type of the function argument (which may be implicitly type-cast), or a compilation error occurs if there is a corresponding function.
1 class A
2 {
3 public:
4 virtual void print () {cout<< "This is A" <<ENDL;}
5};
6 class B:public A
7 {
8 public:
9 void print () {cout<< "Thisisb" <<ENDL;}
10};
11 int main () {
12 {
13 A a;
14 B b;
15 A *p1 = &a;
16 A *p2 = &b;
17 p1->print();
18 p2->print();
19 return 0;
20 }
Here I've attributed the overloads to static polymorphism. The implementation of overloading is that the compiler modifies the names of functions of the same name based on the different parameter tables of the function, and then the functions of the same name are different functions (at least for the compiler). The invocation of the function, which has been determined between the compilers, is static (remember: it is static). In other words, their addresses are bound (early bound) during the compilation period. Because of this nature of overloading, it is also concluded that overloading is only a linguistic feature, independent of polymorphism and irrelevant to object orientation. The concept of overloading based on object-oriented is not "object-oriented Programming". But polymorphism is a relatively broad concept. Here for the sake of understanding first not to depth analysis of their differences, and other parts of the polymorphism of the specific analysis completed, we again.
Dynamic polymorphism
Dynamic binding: The actual type of the referenced object is judged during program execution (non-compile time), and the corresponding method is called according to its actual type. When you use the virtual keyword to decorate a member function of a class, you indicate that the function is a virtual function and the derived class needs to be re-implemented, and the compiler will implement dynamic binding.
FunTest1( cout << << FunTest2( cout << << FunTest3( cout << << FunTest4( cout << << CDerived : FunTest1( cout << << FunTest2( cout << << FunTest3( _iTest1) { cout << << FunTest4( _iTest1, cout << << CBase* pBase = pBase->FunTest1( pBase->FunTest2( pBase->FunTest3( pBase->FunTest4( }
When we use a pointer to a base class or a reference to call a function defined in a base class, we don't know what type the actual object of the function is, because he may be an object of a base class, or it might be an object of a derived class. If the function is a virtual function, it will not be known to the runtime until run time, and it is judged by the true type of the object to which the reference or pointer is bound.
destructors, static type functions, friend functions, inline functions and virtual functions
ctest& = (ctest& * Fri end voi D Funtestfri End (); 12}
What is a virtual function
In fact, in the previous virtual inheritance we have used the concept of virtual function, where we are to solve the diamond common inheritance in the access to the ambiguity of the problem, but in the polymorphic, he has a greater role. Baidu Encyclopedia in the virtual function is said: In a base class declared as virtual and in one or more derived classes are redefined member functions, the usage format is: virtual function return type function name (parameter table) {function Body}; Implements polymorphism by pointing to the base class pointer or reference of a derived class, You access the overridden member function in a derived class with the same name. The image is interpreted as "seeking common ground," and its function is to achieve polymorphism.
Simply 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 to be realized in a common way, but because of individual differences, and adopt different strategies.
1 class A
2 {
3 public:
4 virtual void print () {cout<< "This is A" <<ENDL;}
5};
6 class B:public A
7 {
8 public:
9 void print () {cout<< "Thisisb" <<ENDL;}
10};
11 int main () {
12 {
13 A a;
14 B b;
15 A *p1 = &a;
16 A *p2 = &b;
17 p1->print();
18 p2->print();
19 return 0;
20 }
Undoubtedly, 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. Therefore, the print () of Class B also becomes a virtual function. So for the corresponding function of the derived class if you need to decorate with the virtual keyword, that is your own problem (syntax can be added without adding, the compiler will automatically add, but in order to read convenience and normative, the proposed addition).
Run the code and the output is the result of this is a and this is B.
Summary: A pointer to a base class, when manipulating its Polymorphic class object, invokes its corresponding function according to different class objects, which is a virtual function.
Destructors and virtual functions
When adding the virtual keyword in front of the destructor: Let's analyze the reason.
1, virtual function execution depends on the virtual function table. The virtual function table is initialized in the constructor, that is, initializing the vptr to point to the correct virtual function table. During the construction of the object, the virtual function table is not initialized and will not be able to proceed.
2. When constructing an object, you must know the actual type of the object, and the virtual function behavior is to determine the actual type during run time. While constructing an object, the object has not yet been constructed successfully. The compiler cannot know the actual type of the object, whether it is the class itself, or a derived class of that class, or a deeper derived class. cannot be determined.
The virtual function means that dynamic binding is turned on, and the program chooses the method to invoke based on the object's dynamic type. However, when the constructor is running, the dynamic type of the object is incomplete and there is no way to determine what type it is, so the constructor cannot be bound dynamically. (Dynamic binding is based on the object's dynamic type, not the function name, and before the constructor is called, the object does not exist at all, how does it bind dynamically?) )
The compiler does not know when calling the constructor of the base class whether you are constructing an object of a base class or an object of a derived class.
Static type functions and virtual functions
When we add the virtual keyword in front of the static type function, the error: Analysis:
1. Static members do not belong to any class object or class instance, so even adding virutal to this function is meaningless.
2. The static function does not have this pointer and does not enter the virtual function table. The this pointer cannot be passed to the static function when it is called through a pointer or reference, so that polymorphism cannot be manifested. The difference between a static member function and a normal member function is that the this pointer is missing, and without this pointer, there is no way to know which object the name is a member of.
Friend function and virtual function
When we add the virtual keyword times to the friend function, it's wrong:
Because theC++inheritance of friend functions is not supported, there is no virtual function for functions that do not inherit attributes.
Inline member functions and virtual functions
Inline functions are intended to be expanded directly in the code, reducing the cost of function calls, and virtual functions are not unified in order to perform their actions accurately after inheritance. (Again, theinlinefunction is expanded at compile time, and virtual functions can be dynamically determined at runtime)
Overloading and virtual functions for assignment operators
Compilation can pass when we define overloads of an assignment operator as virtual functions, but it is generally not recommended to do so although operator= can be defined as a virtual function, it is easily confused when used.
1. Cannot assign a value to the own member of the derived class;
2, call virtual function to look up the virtual table, such as a series of operations, efficiency decline.
Destructors and virtual functions
The destructor is set to the virtual function: In the inheritance of the class, if there is a base class pointer to the derived class, then with the base class pointer Delete, if you do not define a virtual function, that part of the derived class cannot be destructor.
1 #include <stdafx.h>
2 #include <stdio.h>
3 Class A
4 {
5 public:
6 A ();
7 virtual~a ();
8};
9a::a ()
10 {}
11 A::~A()
12 {
13 printf("Delete class APn");
14 }
15class B :public A
16 {
17 public:
18 B();
19 ~B();
20 };
21 B::B()
22 { }
23 B::~B()
24 {
25 printf("Delete class BPn");
26 }
27 int main(int argc, char* argv[])
28 {
29 A *b=new B;
30 delete b;
31 return 0;
32 }
The output is: Delete class B Delete class A
If you remove the virtual of a: it becomes delete Class A, which means that the remainder of the derived class is not deleted, or the virtual function of the derived class is not called
Summary of Destructors:
1. If we define a constructor, the compiler will no longer generate a default constructor for us.
2. Compiler-generated destructors are non-virtual, except for a subclass whose parent class has a virtual destructor, at which point the function virtual attribute comes from the parent class.
3. Classes with virtual functions can almost be determined to have a virtual destructor.
4. If a class cannot be a base class, do not declare that the destructor is a virtual function, and the virtual function is space-consuming.
5. An abnormal exit of a destructor causes incomplete destruction and thus a memory leak. It is best to provide a management class that provides a way to deconstruct in the management class, and the caller then decides what to do next, based on the results of this method.
6. Do not call virtual functions in the constructor function. In the construction of a base class, a virtual function is non-virtual and does not go into a derived class, and is both a static binding used. It is obvious that when we construct an object of a subclass, we call the constructor of the base class first, construct the base class part of the subclass, the subclass is not constructed yet, it is not initialized, if you call a virtual function in the construction of the base class, it is dangerous to call an object that has not been initialized, so C + + It is not possible to invoke the virtual function implementation of a subclass when constructing the part of the parent class object. But not that you can not write the program, you write this, the compiler will not error. It's just that if you write this, the compiler will not give you an implementation of the subclass, but rather call the implementation of the base class.
7. Do not call virtual functions in destructors. At the time of the destructor, the destructor of the subclass is called first, then the subclass part of the object is reconstructed, and then the destructor of the base class is called, and if the virtual function is called in the destructor of the base class, it is very dangerous to call the function inside the sub-class object that has been refactored.
8. Remember that when writing a copy function of a derived class, the copy function of the base class is called to copy the part of the base class.
Summarize:
1. The derived class overrides the virtual function of the base class to implement polymorphism, requiring the function name, parameter list, and return value to be exactly the same. (except for covariance).
2. The virtual function is defined in the base class, and in the derived class, the function always retains the attributes of the virtual function.
3. Only non-static member functions of a class can be defined as virtual functions, and static member functions cannot be defined as virtual functions.
4. If you define virtual functions outside of a class, you can only add the virtual keyword when declaring a function, not add it when you define it.
5. Constructors cannot be defined as virtual functions, although operator= can be defined as virtual functions, but it is best not to do so and be easily confused when used.
6. Do not call virtual functions in constructors and destructors, objects are incomplete in constructors and destructors, and undefined behavior may occur.
7, it is best to declare the destructor of the base class as a virtual function. (because the destructor of the derived class is not the same as the destructor name of the base class, but it is an overlay, where the compiler does special processing)
8. Virtual tables are common to all class object instances.