Polymorphism and virtual function (notes)

1, Concept and application of C + + polymorphism

In short: (when the pointer to the base class points to the derived class, the member function of the derived class cannot be accessed. With the help of the declaration of virtual function, the member function of the derived class can be accessed when the pointer to the base class points to the derived class, and then there is polymorphism)

  • The pointer of the base class can also point to the derived class object. See the following example:
#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;
}

Operation results:

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

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 (Zhao Hongjia was originally a Teacher, but the output result shows that he is an unemployed wanderer), which is not in line with our expectations.

  • In other words, you can only access the member variables of the derived class through the base class pointer, but you cannot access the member functions of the derived class.
  • In order to eliminate this embarrassment and enable the base class pointer to access the member functions of derived classes, C + + adds virtual functions. Using virtual functions is very simple. You only need to add the virtual keyword in front of the function declaration.

Change the above code to declare display() as a virtual function:

//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;
};

Operation 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.

  • 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.
  • 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.

2, Detailed explanation of C + + virtual function

Virtual functions play a decisive role in polymorphism. Only virtual functions can form polymorphism. Let's focus on the precautions of virtual functions.

  • 1. You only need to add the virtual keyword at the declaration of the virtual function, and you can or can not add it 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 with masking (covering) relationship in derived classes 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 masks the virtual function of the base class (the function prototype is the same) can it form polymorphism (access the derived class function through the base class pointer).
    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. The 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;

3, C + + pure virtual functions and abstract classes

In C + +, virtual functions can be declared as pure virtual functions. The syntax format is:

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 addition to constraining the functions of derived classes, abstract base classes can also implement polymorphism. Please note that in Line 51, the type of pointer p is Line, but it can access the area() and volume() functions in the derived class. It is precisely because these two functions are defined as pure virtual functions in the Line class; If you don't, the code after Line 51 is wrong.,

#include <iostream>
using namespace std;

//Line
class Line{
public:
    Line(float len);
    virtual float area() = 0;
    virtual float volume() = 0;
protected:
    float m_len;
};
Line::Line(float len): m_len(len){ }

//rectangle
class Rec: public Line{
public:
    Rec(float len, float width);
    float area();
protected:
    float m_width;
};
Rec::Rec(float len, float width): Line(len), m_width(width){ }
float Rec::area(){ return m_len * m_width; }

//Cuboid
class Cuboid: public Rec{
public:
    Cuboid(float len, float width, float height);
    float area();
    float volume();
protected:
    float m_height;
};
Cuboid::Cuboid(float len, float width, float height): Rec(len, width), m_height(height){ }
float Cuboid::area(){ return 2 * ( m_len*m_width + m_len*m_height + m_width*m_height); }
float Cuboid::volume(){ return m_len * m_width * m_height; }

//cube
class Cube: public Cuboid{
public:
    Cube(float len);
    float area();
    float volume();
};
Cube::Cube(float len): Cuboid(len, len, len){ }
float Cube::area(){ return 6 * m_len * m_len; }
float Cube::volume(){ return m_len * m_len * m_len; }

int main(){
    Line *p = new Cuboid(10, 20, 30);
    cout<<"The area of Cuboid is "<<p->area()<<endl;
    cout<<"The volume of Cuboid is "<<p->volume()<<endl;
  
    p = new Cube(15);
    cout<<"The area of Cube is "<<p->area()<<endl;
    cout<<"The volume of Cube is "<<p->volume()<<endl;

    return 0;
}

Tags: C++

Posted on Mon, 06 Sep 2021 20:56:06 -0400 by Alien