Polymorphism is one of the key techniques in object-oriented programming. Using polymorphic techniques, you can invoke functions of the same function name to achieve a completely different function. If the programming language does not support polymorphism, it cannot be called an object-oriented language.
There are two kinds of polymorphism in C + +:
- compile-time polymorphism: implemented by overloading of functions and overloading of operators.
- Runtime polymorphism : Before the program executes, it is not possible to determine which function to call according to the name and parameters of the functions, which must be determined dynamically during program execution, depending on the situation. It is implemented through class inheritance and virtual functions, and it is also used to establish a common program.
Definition of virtual function
1. Define the format
A virtual function is a member function of a class and is defined in the following format:
Virtual return type function name (parameter table);
Description
- The keyword virtual indicates that the member function is a virtual function. Virtual is used only in class definitions, such as virtual functions that are defined outside the class, and cannot be added to virtual.
- When a class member function of a class is defined as a virtual function, the function always retains the characteristics of the virtual function in all derived classes derived from the class.
- When redefining virtual functions in a derived class (overriding a virtual function, also translated as overloaded or overwritten), you do not have to add the keyword virtual. However, the redefinition is not only the same name, but its parameter table and return type are all the same as the virtual function in the base class, otherwise there is an error in the binder.
- The virtual function differs from the second step of "generating a derived class"-The transformation class member, overwriting with the same name (override): If no keyword is virtual, the new member function in the normal derived class overrides the base similar name member function (of course the parameter table must be the same, otherwise overloaded), which can be called the overwrite function with the same name. It is not possible to achieve run-time polymorphism.
2, through virtual function to achieve polymorphism
How does virtual function achieve polymorphism? See below for 2 examples.
① "Example 8.6" calculates credits. Graduate classes can be derived from undergraduates, but their respective algorithms for converting from a course number to a study score are different, and undergraduates are 16 hours a credit, while graduate students are 20 hours a credit. Assignment-compatible rules are associated with custom copy constructors.
#include <iostream>#include<string>using namespacestd;classstudent{stringCoursename;//Course Name intClasshour;//hours intCredit//credits, 0.5 credits not considered Public: Student () {coursename="#"; classhour=0; credit=0;} Virtual voidCalculate () {credit=classhour/ -;} voidSetcourse (stringStrinthour) {Coursename=str; Classhour=hour; } intGethour () {returnClasshour;} voidSetcredit (intCred) {credit=cred;} voidPrint () {cout<<coursename<<'\ t'<<classhour<<"hours"<<'\ t'<<credit<<"credits"<<Endl;}};classGradestudent: Publicstudent{ Public: Gradestudent () {}; voidCalculate () {Setcredit (Gethour ()/ -);}};intMain () {Student S,*PS; Gradestudent G; S.setcourse ("Physical", the); S.calculate (); G.setcourse ("Physical", the); G.calculate (); cout<<"Undergraduate:"<<'\ t'; S.print (); cout<<"graduate Students:"<<'\ t'; G.print (); S.setcourse ("Mathematics", the); G.setcourse ("Mathematics", the); PS=&s; PS-Calculate (); cout<<"Undergraduate:"<<'\ t'; PS-Print (); PS=&G; PS-Calculate (); cout<<"graduate Students:"<<'\ t'; PS-Print (); GetChar (); return 0;}
The result of the operation is:
Undergraduate: Physics 80 hours 5 Credits
Postgraduate: Physics 80 hours 4 Credits
Undergraduate: Mathematics 160 hours 10 credits
Postgraduate: Mathematics 160 hours 8 credits
Analysis:
In the first line, the credits are calculated by the member function calculate () of the student class.
In the second line, the credits are computed by the gradestudent redefined calculate (), which masks the function of the same name as the base class. As with not defined as virtual functions, it is a compile-time polymorphism.
The third line, with a pointer to the object s of the student class, uses the Calculate () of the student class.
The pointer type is a pointer to the base class, but here the pointer points to the object g of the derived class gradestudent, which is permitted by an assignment-compatible rule, but only with the members of the base class, which in effect uses the newly defined calculate () in the derived class. This is the polymorphism of virtual function. If it is not a virtual function, the fourth line of output is 10 credits. If you do not use the base class pointer to point to the object g of the derived class gradestudent, you cannot achieve runtime polymorphism.
② for the advantages of the polymorphism of virtual function, "Example 8.6" can be modified as
#include <iostream>#include<string>using namespacestd;classstudent{stringCoursename;//Course Name intClasshour;//hours intCredit//credits, 0.5 credits not considered Public: Student () {coursename="#"; classhour=0; credit=0;} Virtual voidCalculate () {credit=classhour/ -;} voidSetcourse (stringStrinthour) {Coursename=str; Classhour=hour; } intGethour () {returnClasshour;} voidSetcredit (intCred) {credit=cred;} voidPrint () {cout<<coursename<<'\ t'<<classhour<<"hours"<<'\ t'<<credit<<"credits"<<Endl;}};classGradestudent: Publicstudent{ Public: Gradestudent () {}; voidCalculate () {Setcredit (Gethour ()/ -);}};voidCalfun (Student &ps,stringStrinthour) {PS. Setcourse (Str,hour); Ps. Calculate (); Ps. Print ();}intMain () {Student s; Gradestudent G; cout<<"Undergraduate:"; Calfun (s),"Physical", the); cout<<"graduate Students:"; Calfun (g,"Physical", the);//A derived class object Initializes a reference to the base class, and only calculate () is a virtual function for dynamic polymorphism return 0;}
The result of the operation is:
Undergraduate: Physics 80 hours 5 Credits
Postgraduate: Physics 80 hours 4 Credits
Analysis:
Instead of using pointers, the reference to the compiler, as described in the fourth chapter, is also done indirectly through the address, so the reference can implement runtime polymorphism as well. Student Added a calfun () function, which is more convenient to use.
3. Precautions
It is always good to set all member functions as virtual functions in a class, but be aware of the following:
- A virtual function defined in a derived class must also be the same as the parameter table, with the same return type, except that it must have the same name as a virtual function in the base class. Otherwise, it is considered an overload, not a virtual function. If a base class pointer is returned in a base class, the return derived class pointer in the derived class is allowed, which is an exception.
- Only member functions of a class can be described as virtual functions. This is because the virtual function applies only to class objects that have an inheritance relationship.
- A static member function, which is common to all homogeneous objects, is not restricted to an object and cannot be used as a virtual function.
- An object of the class, which can have static and dynamic types, is essentially the same, but is used in a different way. When you implement dynamic polymorphism, you must use a pointer variable or reference of the base class type so that the pointer points to an object of the different derived classes of the base class and use the virtual function to achieve dynamic polymorphism.
- Inline functions a copy of each object, no mapping relationship, and cannot be a virtual function.
- A destructor can be defined as a virtual function, and the constructor cannot define a virtual function because the object has not yet been instantiated at the time of the constructor. When the memory space is allocated dynamically in the base class and its derived classes, the destructor must be defined as a virtual function that implements the polymorphism when the object is undone.
- Virtual functions perform slightly more slowly. Because, in order to achieve polymorphism, each derived class is to save the corresponding virtual function of the entry Address table, the function of the invocation mechanism is also an indirect implementation. So polymorphism always has to pay a price, but universality is a higher goal.
- If the definition is placed outside the class, virtual can only be added before the function declaration and not (again) in front of the function definition. The correct definition must not include virtual.
The polymorphism and virtual function of VC + +