【Effective C++】条款7:为多态基类声明virtual析构函数

如果你实现的一个类打算作为基类,并且要实现多态,那么就应该将析构函数声明为virtual。

class TimeKeeper
{
public:
	TimeKeeper();
	~TimeKeeper();
};
TimeKeeper::TimeKeeper()
{
	cout << "TimeKeeper构造" << endl;
}
TimeKeeper::~TimeKeeper()
{
	cout << "TimeKeeper析构" << endl;
}

class AtomicClock : public TimeKeeper
{
public:
	AtomicClock();
	~AtomicClock();
};
AtomicClock::AtomicClock()
{
	cout << "AtomicClock构造" << endl;
}
AtomicClock::~AtomicClock()
{
	cout << "AtomicClock析构" << endl;
}


int main()
{
	TimeKeeper* ptr = new AtomicClock;
	delete ptr;
	return 0;
}

可见,父类指针指向子类对象时,当用该指针去调用析构函数,实际上调用的是父类的析构函数,这会导致子类中自己的那部分资源没有得到处理。

解决方案:将父类的析构函数声明为virtual 

virtual ~TimeKeeper();

简单说一下原理:

如果一个类有成员函数是虚函数,那么编译器将会为该类生成一张虚表,存放该类的虚函数地址。

实例化的对象中会额外增加一个虚表指针vptr,该指针指向虚表。

当用父类指针调用虚函数时,从指向的对象中拿到虚表指针,到虚表中找到该类的虚析构函数,再去调用。

你只需记住:任何具有虚函数的类都应有虚析构函数。因为虚函数就是为了实现多态,多态就可能出现上面的情况。

提示一下,多态基类的析构函数要加virtual,子类可加可不加,因为不管你加不加,它都是virtual的。

当一个类不打算成为多态基类时,就不应将析构函数设为虚函数。

原因很简单,因为有虚函数的类实例出的对象中,会额外增加一个指针浪费空间。

STL中的很多类都没有虚析构函数,不要随意继承它们,否则容易出问题

 如果你想要一个抽象类(不能实例化对象),但没有任何纯虚函数时,可以声明一个纯虚析构函数。但是,你必须为该析构函数提供定义。

class AWOV
{
public:
	virtual ~AWOV() = 0;
};
AWOV::~AWOV()
{}

 

纯虚函数的目的就是要求它的子孙类都提供这样一个接口,是为了实现规范,而不是用来调用的,所以一般不用给出定义。但纯虚析构函数必须给出定义,因为子类对象析构时会调用父类的析构函数,如果不提供定义会链接错误。

你可能感兴趣的:(Effective,C++,c++,开发语言)