基类析构函数与虚函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/puliao4167/article/details/85060629

    基类析构函数为什么要声明为虚函数?

    这个问题是C++理解虚函数和动态绑定的一个基础,也是面试常考的一个点。虽然几乎每本书中都会提及这个点,但是很少有把其具体阐明。本文通过具体实例+理论阐述尽量清晰解释这个问题。

    首先看一下effective c++中是怎么描述的。

   ----摘自《Effective C++》

    C++中明白指出,当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual 析构函数,其结果未有定义——实际执行时通常发生的是对象的derived成分没有销毁,然而其base class成分通常会被销毁,于是造成一个诡异的“局部销毁”对象。

    要明白基类析构函数为什么要声明为虚函数,首先要理解几个点。

  1. 动态绑定。绑定的是动态类型,就是对应的函数或者属性依赖于对象的动态类型,是在运行阶段确定的,不是编译阶段(静态类型)。实例就是基类指针指向派生类,指向的是派生类中基类部分
  2. 在继承体系中,构造函数和析构函数的执行顺序。对于构造函数而言,是“从内而外”,具体指的是基类的构造函数先调用,然后才调用派生类的构造函数;对于析构函数而言,则是刚刚反过来,先调用派生类的析构函数,然后再调用基类的析构函数。
  3. 每个析构函数只能管理自己类中的元素。

    直接上代码吧。

#include <iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		cout << "Base constructor" << endl;
	}
	virtual ~Base()
	{
		cout << "Base destructor" << endl;
	}

private:

};

class Derived:public Base
{
public:
	Derived():P(new int)
	{
		cout << "Derived constructor" << endl; 
	}

	~Derived()
	{
		delete p;
		cout << "Derived destructor" << endl; 
	}

private:
	int *p;
};

int main()
{
	Base *base =new Derived();
	delete base;
	system("pause");
	return 0;
}

    正常的基类中析构函数定义了virtual ,就会正常输出。

    当把基类的析构函数virtual去掉,就会只调用基类析构,而不调用派生类的析构函数。这样就会导致一些问题,因为在派生类构造的时候动态分配了一些内存,当派生类析构函数没有调用时候,就会出现内存泄漏,同时派生类的成员也不会被销毁。

     综上,不一定所有的类都要把析构函数定义为虚函数,因为一旦定义为虚函数,其内存中就会增加4字节的虚指针,但是为了对内存泄漏做到“零容忍”,建议只要这个类可能作为基类,都将其析构函数声明为virtual。总体来说,基类虚函数声明为virtual是为了在动态绑定时防止内存泄漏。

猜你喜欢

转载自blog.csdn.net/puliao4167/article/details/85060629
今日推荐