polymorphic
What is polymorphism? Multiple forms and polymorphisms of the same thing in different scenarios can make the interface of functions universal.
One of the three characteristics of object-oriented
Advantages: clear code organization structure; Strong readability; It is conducive to early and later expansion and maintenance (based on the opening and closing principle: in the object-oriented field, the opening and closing principle stipulates that "objects (classes, modules, functions, etc.) in software should be open for expansion, but closed for modification", which means that an entity is allowed to change its behavior without changing its source code.)
Disadvantages: it reduces the running efficiency of the program (polymorphism needs to find the address of the virtual table); Waste of space
Static polymorphism and dynamic polymorphism
1. Static polymorphism: function overloading and operator overloading. Static polymorphism is completed by the compiler during compilation. The compiler will choose to call the appropriate function according to the argument type. If there is an appropriate function to call, it will call it. If there is no function, it will issue a warning or an error
2. Dynamic polymorphism: derived classes and virtual functions implement runtime polymorphism. When the program runs, it determines which class virtual function to call according to the object pointed to by the reference (pointer) of the base class.
#include <iostream> using namespace std; class animal { public: void speak() { cout << "animal speak" << endl; } }; class cat : public animal { public: void speak() { cout << "cat speak" << endl; } }; void create(animal &m) { m.speak(); } void test() { cat CAT; create(CAT); } int main(void) { test(); system("pause"); return 0; }
Because the address of the function is determined during compilation, this program calls the base class function instead of the derived class function.
If dynamic polymorphism is used
#include <iostream> using namespace std; class animal { public: virtual void speak()//virtual function { cout << "animal speak" << endl; } }; class cat : public animal { public: void speak() { cout << "cat speak" << endl; } }; void create(animal &m) { m.speak(); } void test() { cat CAT; create(CAT); } int main(void) { test(); system("pause"); return 0; }
The virtual keyword virtual is added in front of the function to create a virtual function to form a polymorphism. When the program runs, the function address is established through the object (derived class member) pointed to by the reference of the base class. Therefore, the derived class function is called instead of the base function.
Therefore, the composition conditions of dynamic polymorphism are:
1. The base class must contain virtual functions, and the derived class must override the virtual functions in the base class.
2. Virtual functions are called through pointers or references to base class objects.
rewrite:
(a) The function to be overridden in the base class must be a virtual function
(b) The prototypes of virtual functions in base and derived classes must be consistent (return value type, function name and parameter list), except covariant and destructor (destructors of base and derived classes are different)
**Covariance: * * the virtual function of the base class (or derived class) returns the pointer (Reference) of the base class (derived class)
Which functions cannot be used as virtual functions?
1) Friend function, which is not a member function of a class
2) Global function
3) Static member function, which has no this pointer
3) Constructor, copy constructor, and assignment operator overloading (yes, but generally not recommended as virtual functions)
Template
Template is to establish a general mold, which greatly improves the reusability. It is a polymorphic mechanism
In C + +, templates are divided into function templates and class templates.
-
Function templates are used to generate functions;
-
Class templates are used to generate classes.
Function template
//format template <class Type parameter 1, class Type parameter 2, ...> Return value type template name(Formal parameter table) { Function body } /*Where class can be replaced by typename. template <typename Type parameter 1, typename type parameter 2,... >*/
Use case: implement data exchange function template
template <class T> void Swap(T & x, T & y) { T tmp = x; x = y; y = tmp; }
When compiling the statement calling the function template, the compiler will judge how to replace the type parameter in the template according to the type of the argument. If the type of the argument is int, the compiler will automatically replace T with int and automatically generate the function.
The process by which the compiler automatically generates functions from templates is called template instantiation. The function obtained by template instantiation is called template function.
-
Function templates can have more than one type parameter
-
The type parameters in the template can not only be instantiated through the arguments of the template call statement. The template call statement can clearly indicate the type to instantiate the type parameters.
Template function name<data type>(Parameter 1, Parameter 2)
-
In function templates, type parameters can be used not only to define the types of parameters, but also to define the return values of local variables and function templates.
-
When the function template and ordinary function exist at the same time, the function template shall be called first.
Class template
A class template is a feature abstraction about a set of classes.
Why do I need a class template?
Sometimes you need two or more templates with the same functions but different data types, so you need to establish a general class.
Syntax:
template <typename T> class Tclass{ }; //Class in < class T > is used to indicate that t is a type parameter. T is not necessarily a class, but also a basic type
- The class template is used to parameterize the type of data required by the class
- Class templates are particularly important in representing data structures such as arrays, tables, graphs and so on
- The representation and algorithm of these data structures are not affected by the type of elements contained
- Class templates do not use automatic type derivation
- Class templates can have default parameters in the template parameter list
- The member function of a class template is created when called (the member function of a normal class is created at the beginning)
Class template object as function parameter
-
Specify data type on incoming (most commonly used)
void printPerson1(Person<string, int> &p) { p.showPerson(); }
-
Parameter Templating
template <class T1, class T2> void printPerson1(Person<T1, T2> &p) { p.showPerson(); }
-
Class template incoming
template <class T> void printPerson1(T &p) { p.showPerson(); cout << "T Type of:" << typeid(T).name() << endl;//The typeid() function represents the name of the type }
Class template and inheritance
The derived class inherits the class template of the base class. You need to know the data type in the base class to inherit.
template <class T> class Base { public: T m; }; class person :public Base<int> { public: //...... };
If you want to flexibly specify the base class data type, the derived class needs to be defined as a class template
template <class T> class Base{ public: T m; }; template <class T1> class person:public Base<T1> { public: //...... };
Out of class implementation of class template member function
The parameter list of the class template shall be added to the out of class implementation of the class template member function
//Class template constructor out of class implementation template <class T1, class T2> person<T1, T2>::person(T1 name, T2 age) { this->name = name; this->age = age; } //Class template member function out of class implementation template <class T1, class T2> person<T1, T2>:: show() { }
Class templates and friends
virtual function
Virtual function: a member function modified by the virtual keyword is a virtual function.
Function: realize polymorphism. Polymorphism is to separate the interface from the implementation. Allows you to redefine functions with the same name as the base class in derived classes, and you can access functions with the same name in base and derived classes through base class pointers or references.
The implementation of virtual function consists of two parts: virtual function pointer and virtual function table
The compiler will create a virtual function table for each class containing virtual functions, and store all virtual function addresses of the class in the table. At the same time, the compiler will automatically create a virtual function pointer for each object containing a virtual function class (the virtual function pointer is actually a function pointer), which points to the virtual table of the class. When a subclass calls a virtual function, it actually calls the virtual function pointer to find the interface.
For single inheritance, that is, when the derived class inherits only one base class, the derived class has only one virtual function table, and the virtual function table of the base class is different from that of the derived class. If the derived class does not override the virtual function of the base function, the addresses of the two virtual function tables are the same. When the derived class overrides the virtual function of the base function, the virtual function address of the derived class will overwrite the address of the base function.
In the case of multiple inheritance, there are multiple virtual function tables in the derived class, and the arrangement of virtual functions is consistent with the order of inheritance. The derived class rewriting function will overwrite the contents of all virtual function tables with the same name. The new virtual function defined by the derived class will be expanded after the virtual function table of the first class.
Pure virtual functions and abstract classes
Meaning of pure virtual function: for some programs, the content of the base class virtual function has no practical significance, so the virtual function can be rewritten as pure virtual function (no function body) virtual int sum() = 0;
When there are pure virtual functions in a class, the class is also called an abstract class
Characteristics of abstract classes:
There are objects without instances; Derived classes must override pure virtual functions of abstract classes
You can point to the derived class object through the pointer and reference of the base class, and call the interface through the this pointer.
Virtual destruct and pure virtual destruct
If the attribute of the derived class is opened to the heap, the pointer of the base class cannot call the destructor of the derived class during destruction, resulting in memory leakage.
Solution: use virtual destruct and pure virtual destruct (both virtual destruct and pure virtual destruct need the specific implementation of the function)
Virtual destructor format: virtual ~person() {}