Three characteristics of C + + object-oriented -- polymorphism

catalogue

1: Concept of C + + polymorphism  

2: Implementation of C + + polymorphism

3: C + + virtual function

1. Items needing attention when using virtual functions        

  2. Pure virtual function

1: Concept of C + + polymorphism  

        "Polymorphism" means that things with the same name can perform different functions. Polymorphism can be divided into compile time polymorphism and run-time polymorphism. The former mainly refers to function overloading (including operator overloading) and calling overloaded functions. Which function should be called can be determined according to the actual parameters at compile time, so it is called polymorphism at compile time; The latter is related to the concepts of inheritance and virtual function.

         Polymorphism is one of the main features of object-oriented programming. The only use of virtual functions in C + + is to form polymorphism

         The purpose of providing polymorphism in C + + is to provide "all-round" access to member variables and member functions of all derived classes (including direct derivation and indirect derivation) through base class pointers, especially member functions. Without polymorphism, we can only access member variables.  

         Speaking of this, students who are new to C + + may not understand the above two paragraphs marked in red, so let's learn what virtual functions are, under what conditions they form polymorphism, and what are the benefits of polymorphism through examples  

#include <iostream>
using namespace std;
//Base class People
class People{
public:
    People(char *name, int age);
    void display();
protected:
    char *m_name;
    int m_age;
};
People::People(char *name, int age): m_name(name), m_age(age){}
void People::display(){
    cout<<m_name<<"this year"<<m_age<<"Years old, a homeless man."<<endl;
}
//Derived class Teacher
class Teacher: public People{
public:
    Teacher(char *name, int age, int salary);
    void display();
private:
    int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){
    cout<<m_name<<"this year"<<m_age<<"Years old, is a teacher, every month"<<m_salary<<"Yuan of income."<<endl;
}
int main(){
    People *p = new People("Zhi Gang Wang", 23);
    p -> display();
    p = new Teacher("Zhao Hongjia", 45, 8200);
    p -> display();
    return 0;
}

1. Define a People class. We provide a constructor and a member function display.

2. Define a Teacher class, inherit the People class, and also provide a constructor and a member function display with the same name

3. Define a base class pointer p in the main function to point to the instantiated base class object. Call the display function through p, which will undoubtedly call the display function of the base class

4. The pointer p points to the instantiated Teacher class object. In this case, call the display function through p. then, do you call the display function of the base class or the display function of Teacher class

Let's first look at the results of the program

Wang Zhigang is 23 years old. He is an unemployed vagrant.
Zhao Hongjia is 45 years old. He is an unemployed vagrant.

          You can see that both calls to the display function are based on the called base class, but the member variables are self-contained. We intuitively believe that if the pointer points to the derived class object, we should use the member variables and member functions of the derived class, which is in line with people's thinking habits. However, the running result of this example tells us that when the base class pointer p points to the object of the derived class Teacher, although the member variable of Teacher is used, its member function is not used, resulting in different output results.

          Through the base class pointer, you can only access the member variables of the derived class, but you cannot access the member functions of the derived class

2: Implementation of C + + polymorphism

         In order to eliminate the embarrassment of the above scenario, the base class pointer can access the member functions of the derived class, C++   Virtual Function is added. Using a Virtual Function is very simple. You only need to add it in front of the function declaration   virtual   keyword. So can virtual functions really achieve the effect we mentioned above? It's useless to say more. Let's take a specific example below

#include <iostream>
using namespace std;
//Base class People
class People{
public:
    People(char *name, int age);
    virtual void display();  //Declare as virtual function
protected:
    char *m_name;
    int m_age;
};
People::People(char *name, int age): m_name(name), m_age(age){}
void People::display(){
    cout<<m_name<<"this year"<<m_age<<"Years old, a homeless man."<<endl;
}
//Derived class Teacher
class Teacher: public People{
public:
    Teacher(char *name, int age, int salary);
    virtual void display();  //Declare as virtual function
private:
    int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){
    cout<<m_name<<"this year"<<m_age<<"Years old, is a teacher, every month"<<m_salary<<"Yuan of income."<<endl;
}
int main(){
    People *p = new People("Zhi Gang Wang", 23);
    p -> display();
    p = new Teacher("Zhao Hongjia", 45, 8200);
    p -> display();
    return 0;
}

The only difference between the code and the above is that display precedes the function declaration with the keyword virtual

Let's look at the running results

Wang Zhigang is 23 years old. He is an unemployed vagrant.
Zhao Hongjia, 45, is a teacher with a monthly income of 8200 yuan.

         Compared with the previous example, this example only adds a virtual keyword before the declaration of the display() function, and declares the member function as a Virtual Function, so that the member function of the Teacher class can be called through the p pointer. The running results also prove this (Zhao Hongjia is already a Teacher and no longer a vagrant).

         With virtual functions, when the base class pointer points to the base class object, the members of the base class (including member functions and member variables) are used, and when it points to the derived class object, the members of the derived class are used. In other words, the base class pointer can do things in the way of the base class or the derived class. It has many forms or manifestations. We call this phenomenon Polymorphism.

         When calling an ordinary member function through a pointer, the member function of which class will be called will be judged according to the type of the pointer (the pointer defined by which class). However, this statement does not apply to virtual functions. Virtual functions are called according to the point of the pointer, and the virtual function of which class will be called according to the object of which class the pointer points to.

         For large and medium-sized programs with complex inheritance relationships, polymorphism can increase their flexibility and make the code more expressive

3: C + + virtual function

1. Items needing attention when using virtual functions        

Since virtual functions play a decisive role in polymorphism, only virtual functions can form polymorphism, so it is necessary for us to study virtual functions separately.

1) You just need to add   virtual keyword, which can be added or not added at the function definition.

2) For convenience, you can only declare the functions in the base class as virtual functions, so that all functions with the same name in the derived class with masking relationship will automatically become virtual functions.

3) When a virtual function is defined in the base class, if the derived class does not define a new function to mask the function, the virtual function of the base class will be used.

4) Only when the virtual function of the derived class covers the virtual function of the base class (the function prototype is the same) can it form polymorphism (through the base class) Pointer Access derived class functions). For example, the prototype of the virtual function of the base class is virtual void func();, The prototype of the derived virtual function is virtual void func(int);, Then, when the base class pointer P points to the derived class object, the statement p - > func (100); An error will occur, and the statement p - > func(); The function of the base class will be called.

5) Constructor cannot be a virtual function. For the constructor of the base class, it is only called in the constructor of the derived class. This mechanism is different from inheritance. In other words, the derived class does not inherit the constructor of the base class, and it is meaningless to declare the constructor as a virtual function.

6) Destructors can be declared as virtual functions, and sometimes must be declared as virtual functions  

  As mentioned above, only virtual functions can form polymorphism. Is it true that only virtual functions can form polymorphism? Do you need other conditions to form polymorphism? The following three conditions must be met to form polymorphism

  • Inheritance relationship must exist;
  • There must be virtual functions with the same name in the inheritance relationship, and they are coverage relationships (the function prototypes are the same).
  • There is a pointer to the base class through which the virtual function is called.

  The following examples illustrate various chaotic situations:

#include <iostream>
using namespace std;
//Base class base
class Base{
public:
    virtual void func();
    virtual void func(int);
};
void Base::func(){
    cout<<"void Base::func()"<<endl;
}
void Base::func(int n){
    cout<<"void Base::func(int)"<<endl;
}
//Derived class
class Derived: public Base{
public:
    void func();
    void func(char *);
};
void Derived::func(){
    cout<<"void Derived::func()"<<endl;
}
void Derived::func(char *str){
    cout<<"void Derived::func(char *)"<<endl;
}
int main(){
    Base *p = new Derived();
    p -> func();  //Output void Derived::func()
    p -> func(10);  //Output void Base::func(int)
    p -> func("http://c.biancheng.net");  //compile error
    return 0;
}

         In the Base class, we declare void func() as a virtual function, so void func() in Derived class will automatically become a virtual function. p is a pointer to the Base class, but points to an object of the Derived class Derived.

         Statement p - > func(); What is called is the virtual function of the derived class, which constitutes polymorphism.

         Statement p - > func (10); The virtual function of the base class is called because no function in the derived class overrides it.

         Statement p - > func(“ http://c.biancheng.net "); A compilation error occurred because only the members inherited from the base class can be accessed through the pointer of the base class, and the new members of the derived class cannot be accessed.

        So when to declare a virtual function

         First, see whether the class where the member function is located will be used as the base class. Then see if the function of the member function may be changed after the inheritance of the class. If you want to change its function, you should generally declare it as a virtual function. If the function of a member function does not need to be modified after the class is inherited, or the derived class does not use the function, do not declare it as a virtual function.

  2. Pure virtual function

  I believe that when I come into contact with C + + or interview, I will more or less meet the figure of pure virtual functions. Adding a "" pure "" sub indicates that this function is true and virtual. The involved classes that define pure virtual functions cannot be instantiated.

  Pure virtual function, syntax format:

virtual return value type function name (function parameter) = 0;

A pure virtual function has no function body but only a function declaration. Adding = 0 at the end of the virtual function declaration indicates that the function is a pure virtual function.  

The last = 0 does not mean that the return value of the function is 0. It only plays a formal role and tells the compilation system that "this is a pure virtual function".  

         A class containing pure virtual functions is called an Abstract Class. It is abstract because it cannot be instantiated, that is, it cannot create objects. The reason is obvious. Pure virtual functions have no function body, are not complete functions, and cannot be called or allocated memory space.  

         Abstract classes are usually used as base classes to allow derived classes to implement pure virtual functions. A derived class must implement a pure virtual function to be instantiated.  

         In actual development, you can define an abstract base class, which only completes some functions, and the unfinished functions are handed over to the derived class to implement (who derives and who implements). These unfinished functions are often unnecessary or impossible to implement in the base class. Although the abstract base class is not completed, it is mandatory for the derived class to complete. This is the "overlord clause" of the abstract base class.

Some notes on pure imaginary functions

1) A pure virtual function can make a class an abstract base class, but the abstract base class can contain other member functions (virtual functions or ordinary functions) and member variables in addition to pure virtual functions.

2)   Only virtual functions in a class can be declared as pure virtual functions. Neither ordinary member functions nor top-level functions can be declared as pure virtual functions

 

Keywords: C++ Polymorphism

Added by 1042 on Sat, 20 Nov 2021 15:43:42 +0200