C++虚析构函数

C++虚析构函数

一般来说,用new运算符动态生成的对象都是通过delete指向它的指针来释放的,例如

Base1 *p = new Base1;
delete p;

 但是我们有时会让一个基类指针指向用new运算符动态生成的派生类对象,例如以下程序:


#include 
using namespace std;

//基类Base1
class Base1
{
public:
	Base1() 
	{
		cout << "Base1构造函数" << endl;
	}
	~Base1()
	{
		cout << "~Base1析构函数" << endl;
	}
};

//派生类Base2
class Base2 : public Base1
{
public:
	Base2()
	{
		cout << "Base2构造函数" << endl;
	}
	~Base2()
	{
		cout << "~Base2析构函数" << endl;
	}
};

int main() 
{
	//基类指针指向用new运算符动态生成的派生类对象
	Base1 *base1=new Base2;

	delete base1;

	return 0;
}

 

运行结果:

C++虚析构函数_第1张图片

显然,语句“ delete base1; "只引发了基类Base1析构函数的调用,派生类Base2的析构函数没有被调用,而释放内存的操作都是在析构函数中进行的,所以析构函数不被调用的话就会造成内存泄漏。

原因分析:因为此语句是静态联编的,编译到此处时,编译器无法获知指针base1实际指向的对象究竟为哪个类型,它只会根据base1的类型是Base1 *来决定调用Base1类的析构函数。

而我们的期望是当使用一个基类的指针去删除一个派生类的对象时,派生类的析构函数能被调用。即执行语句“ delete base1; "时,编译器会根据base1所指向的对象执行相应的析构函数。

而在C++中,只需将基类的析构函数声明为虚函数即可,即虚析构函数,可通过在析构函数前加virtual关键字实现,例如将以上程序的基类Base1的析构函数声明为虚析构函数,如下:

//基类Base1
class Base1
{
public:
	Base1() 
	{
		cout << "Base1构造函数" << endl;
	}
	virtual ~Base1()      //在析构函数前加上virtual关键字
	{
		cout << "~Base1析构函数" << endl;
	}
};

运行结果:

C++虚析构函数_第2张图片

此时,派生类Base2的析构函数被调用了,实际上,派生类的析构函数会自动地调用基类的析构函数。

备注:

1.只要基类的析构函数是虚函数,那么派生类的析构函数不论是否用virtual关键字声明,都自动成为虚析构函数,即使派生类的析构函数与基类的析构函数名字不相同。

2.一般来说,一个类如果定义了虚函数,则最好将析构函数也定义为虚函数。

3.析构函数可以是虚函数,但构造函数不能声明为虚函数,这是因为在执行构造函数时类对象还未完成建立过程,当然谈不上函数与类对象的绑定。

 

 

 

 

 

 

你可能感兴趣的:(C++学习)