Base class pointers, derived class pointers and virtual functions in C++ inheritance

In C++, Inheritance is one of the core ideas of object-oriented programming. It builds a hierarchical relationship between classes, with the concepts of parent classes and subclasses. This article will summarize the relevant content of base class pointers, derived class pointers and virtual functions, and attach corresponding sample codes.

1. Base class pointer, derived class pointer

In C++, a parent class pointer can new a subclass object, but a subclass pointer cannot new a parent class object. The parent class pointer can call the member functions of the parent class, but cannot call the member functions of the subclass, because the parent class pointer can only access the member variables and member functions of the parent class.

//Define base class/parent class/super class
//Human.h file
//Define base class/parent class/super class

#ifndef _HUMAN_
#define _HUMAN_

#include<iostream>

classHuman
{<!-- -->
public:
Human();
virtual ~Human();
Human(int);
public:
//virtual void eat() /*final*/;//Declared as a virtual function

virtual void eat2() = 0;//Pure virtual function, no function body and only one function declaration
public:
int m_Age;//Age
char m_Name[100];//name
void funchuman() {<!-- -->};

void funcpub()
{<!-- -->
std::cout << "Human::funcpub()" << std::endl;
};
public:
void samenamefunc();
void samenamefunc(int);
protected:
int m_pro1;
void funcpro()
{<!-- -->
std::cout << "Human::funcpro()" << std::endl;
};
private:
int m_priv1;
void funcpriv() {<!-- -->};


};//When defining or declaring a class, don’t forget the; at the end.
#endif // _HUMAN_

//Human.cpp file Human.cpp file Human.cpp file
#include"Human.h"
#include<iostream>

//Implementation of Human class

Human::Human()//Constructor without parameters (default constructor)
{<!-- -->
std::cout << "The Human::Human() constructor was executed" << std::endl;
}

Human::~Human()
{<!-- -->
std::cout << "The Human::~Human() destructor was executed" << std::endl;
}

Human::Human(int abc)//Constructor with one parameter
{<!-- -->
std::cout << "The Human::Human(int abc) constructor was executed" << std::endl;
}

void Human::samenamefunc()
{<!-- -->
std::cout << "Human::samenamefunc()" << std::endl;
}

void Human::samenamefunc(int)
{<!-- -->
std::cout << "Executed Human::samenamefunc(int)"<<std::endl;
}

//void Human::eat()//Declared as a virtual function
//{<!-- -->
// std::cout << "Humans eat all kinds of food" << std::endl;
//}

//Men.h file Men.h file Men.h file
//Define the subclass Men of Human
//Define the subclass Men of Human

#ifndef _MEN_
#define _MEN_

#include"Human.h"
#include<iostream>
//man
class Men: public Human//Indicates that Men is a subclass of Human
//class Men : protected Human
//class Men: private Human
{<!-- -->
public:
Men();
~Men();

public:
void funcmen() {<!-- -->};
void samenamefunc(int);

public:
using Human::samenamefunc;
public:
//virtual void eat() override;
virtual void eat2()
{<!-- -->
std::cout << "Men::eat2()"<<std::endl;
};

};//When defining or declaring a class, don’t forget the; at the end.
#endif // _MEN_

//MEN.cpp MEN.cpp MEN.cpp
#include"Men.h"
#include<iostream>

//Implementation of subclass Men
Men::Men()
{<!-- -->
//funcpro();
std::cout << "The Men::Men() constructor was executed"<<std::endl;
}

Men::~Men()
{<!-- -->
std::cout << "The Men::~Men() destructor was executed" << std::endl;
}

void Men::samenamefunc(int)
{<!-- -->
//Human::samenamefunc(12);//Force to call the same-name function of the parent class
//Human::samenamefunc();//Force to call the same-name function of the parent class
std::cout << "void Men::samenamefunc(int)" was executed" << std::endl;
}

//void Men::eat()
//{<!-- -->
// std::cout << "Men like to eat rice" << std::endl;
//}

//Main file.cpp Main file.cpp Main file.cpp
#include<iostream>
#include"Human.h"
#include"Men.h"
#include"Women.h"

int main()
{<!-- -->
    Human* phuman = new Men; // Can be compiled
    Men* pmen = new Human; // Error reported, compilation failed
    phuman->funchuman(); // The parent class type pointer can call the member function of the parent class
    phuman->funcmen(); // Error, cannot call subclass member function
    return 0;
}

Concept introduction: Since the parent class pointer cannot call the member functions of the subclass, why do you need the parent class pointer to create a new subclass object?

2. Virtual function

Virtual function is declared in parent class, subclass can override this function. When calling a virtual function, it will be dynamically bound, that is, when the program is running it can determine which subclass function to call strong>. When the parent class pointer calls a virtual function, the function of the same name of the subclass will be called.

 Human* phuman = new Human;
phuman->eat();//The eat function of the parent class is called, because phuman is a parent class pointer.
So how to call the eat function of Men and Women?

Men* pmen = new Men;
pmen->eat();//Call the eat() of the subclass Men

Women* pwomen = new Women;
pwomen->eat();//Call the eat() of the subclass Women
The above method is too **trouble**. Is there a **solution**? We **only define an object pointer** and can **call the parent class** and **functions of the same name of each subclass* *Woolen cloth?
There are: **This object pointer, its type must be the parent class type (Human *phuman). **
If we want to call a function with the same name and parameters in the parent class or subclass through a parent class pointer, the requirements for this function are:
In the parent class, before the **function (eat() function) is declared, the virtual declaration function (eat() function) must be added as a virtual function**
**Once a function (in the base class) is declared as a virtual function, it is also declared as a virtual function in the derived class (subclass)**
\t  
Human* phuman1 = new Men;
phuman1->eat();//The parent class’s eat() is called;

eat() is declared as a virtual function
Human* phuman = new Men;
phuman->eat(); //The eat() function of the subclass Men is called
phuman->Human::eat();//Call the eat() function of the parent class
delete phuman;
If not declared as a virtual function:
Human* phuman = new Men;//Can be compiled
phuman->eat();//The eat() function of the parent class (Human) is called, because phuman is a parent class pointer.

phuman = new Women;
phuman->eat();//The eat() function of the subclass Women is called
delete phuman;

phuman = new Human;
phuman->eat();//The eat() function of the parent class Human is called
delete phuman;

3. Override and final keywords

In C++11, you can add the override keyword to the function declaration to indicate that the virtual function in the derived class overrides the function of the same name in the parent class . If the virtual function in the subclass has the wrong name or parameters, the compiler will report an error.

**In order to avoid you writing the wrong virtual function in the subclass (such as inconsistent parameters)**, in C++11, you can **add an override keyword** to the function declaration, this The keyword, ** is used in "subclasses" and is dedicated to virtual functions. **

**override** is used to describe the **virtual function** in the **derived class**. After you use this keyword, the compiler will think that your eat overrides the function of the same name in the parent class** (Only virtual functions have the problem that subclasses can overwrite functions with the same name in the parent class)**, then the compiler will look for a virtual function with the same name and parameters in the parent class. If it is not found, the compiler will report an error, so , if you accidentally write the wrong name and wrong parameters of the virtual function in the subclass, the compiler can help you correct the error.

final, final is also dedicated to virtual function, but it is used in “parent class”, if we < strong>If final is added to the function declaration of the parent class, then any attempt to override the function will trigger an error

Call virtual function execution is **” dynamic binding ” Dynamic **: It means that we can only know which subclass’s eat() virtual function has been called when our program is running.
Dynamically tied to Men and Women, depending on whether the new one is Men or Wonmen

Summarize:
Dynamic binding: It is decided when running that your phuman object is bound to which eat() function to run;
Men men;
men.eat();//The call must be Men;
Women women;
women.eat();//The call must be Wonmen
Human human;
human.eat();//The call must be Human

Virtual functions are generally operated using pointers, otherwise the effect of the virtual function will not be reflected

syntaxbug.com © 2021 All Rights Reserved.