Virtual destructor of C++ base class interface design

1. Description of the problem:
Recently, a memory leak has occurred when using an abstract class as an interface. By reading related articles, it was found that the base class destructor was not set as a virtual function during construction.
2. Related concepts:
(1) Virtual function: A member function declared as virtual in a base class and redefined in one or more derived classes is called a virtual function.

virtual void fun();

(2) Pure virtual function: A member function declared as the following form is a pure virtual function and has not been implemented.

virtual void fun() = 0;

(3) Abstract class: A class with a member function that is a pure virtual function—an abstract class cannot be instantiated.

class Father0
{
    
    
public:
	virtual ~Father0(){
    
    }
	virtual void fun() = 0;
};

3. Virtual function realizes polymorphism
After defining a virtual function, it can be rewritten in a derived class to realize a unified interface and different execution processes. Dynamically select the appropriate member function during the function running phase.
The relevant implementation code is as follows:

#include <iostream>
using namespace std;
class Father0
{
    
    
public:
	virtual ~Father0(){
    
    }
	virtual void fun() = 0;
};
class Father: public Father0
{
    
    
public:
	Father() 
	{
    
    
		cout << "class Father init" << endl;
	}
	virtual ~Father() 
	{
    
    
		cout << "class Father destroyed" << endl;
	}
	void fun0()
	{
    
    
		cout << "this is a base function" << endl;
	}
	virtual void fun()
	{
    
    
		cout << "this is a virtual function" << endl;
	}
};
class Son1 : public Father 
{
    
    
public:
	Son1() 
	{
    
    
		cout << "class Son1 init" << endl;
	}
	~Son1() 
	{
    
    
		cout << "class Son1 destroyed" << endl;
	}
	void fun()
	{
    
    
		cout << "this is a virtual function of Son1" << endl;	
	}
};
class Son2 : public Son1 
{
    
    
public:
	Son2()
	{
    
    
		cout << "class Son2 init" << endl;
	}
	~Son2() 
	{
    
    
		cout << "class Son2 destroyed" << endl;
	}
	void fun11()
	{
    
    
		cout << "this is a virtual function of Son2" << endl;
	}
};
int main() 
{
    
    
	Father0* p;
	p= new Son2;
	p->fun();
	delete p;
	system("pause");
	return 0;
}

Build the abstract class Father0, point to the subclass through the pointer of Father0, and realize different functions (polymorphism) when pointing to different subclasses.
When using the abstract class pointer to point to the subclass Son2, the constructor starts from the parent class, and the destructor does the opposite. In addition, in the case of multiple inheritance, if the pointed subclass does not have a function to be called, it is searched and called to the upper level. The result of running is as follows:

/*
class Father init
class Son1 init
class Son2 init
this is a virtual function of Son1
class Son2 destroyed
class Son1 destroyed
class Father destroyed
*/

When the destructor of the abstract class is not set as a virtual function, only the pointer class will be released when it is destructed. In the above code, if the virtual of the destructor of the Father0 class is canceled, the following operation results will be produced:

/*
class Father init
class Son1 init
class Son2 init
this is a virtual function of Son1
*/

In addition, if the virtual function of the destructor of the Father0 class is canceled, the destructor of the Father class is set as a virtual function, and the pointer is changed to Father, the following operation results will be produced:

/*
class Father init
class Son1 init
class Son2 init
this is a virtual function of Son1
class Father destroyed
*/

If only the pointer is changed to Father, the following operation results will be produced:

/*
class Father init
class Son1 init
class Son2 init
this is a virtual function of Son1
class Son2 destroyed
class Son1 destroyed
class Father destroyed
*/

4. Conclusion
When implementing polymorphism by constructing virtual functions, you must remember to set the destructor of the base class as a virtual function. In addition, if the base class pointer is not used, there is no need to set the destructor of the base class as a virtual function.
If will

Father0* p;
p= new Son2;

changed to

Son2* p;
p= new Son2;

Then the running result is:

/*
class Father init
class Son1 init
class Son2 init
this is a virtual function of Son1
class Son2 destroyed
class Son1 destroyed
class Father destroyed
*/

Finally, friends who are interested in destructors can check the references below.

References:
[1] Why the destructor must be a virtual function
[2] Virtual function and polymorphism
[3] Detailed c++ virtual function

Guess you like

Origin blog.csdn.net/qq_44924694/article/details/129819621