条款7:为多态基类声明virtual析构函数

本文探讨了C++中析构函数的正确使用方法,特别是在继承体系中的作用。文章强调了虚析构函数的重要性,并讨论了其如何避免资源泄露,同时提到了纯虚析构函数的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(一)如下继承关系:

class TimeKeeper {
public:
	TimeKeeper();
	~TimeKeeper();           //non_virtua
};
class AtomicClock : public TimeKeeper {...}; //原子钟
class WaterClock : public TimeKeeper{...}; //水钟
class WristWatch : public TimeKeeper{...}; //腕表
factory(工厂)函数,返回一个base class指针,指向新生成的derived class对象

//TimeKeeper* getTimeKeeper(); //返回一个指针,指向一个TimeKeeper派生类的动态分配对象
TimeKeeper* ptk = getTimeKeeper();
...
delete ptk;

ptk指向一个derived class对象(例如AtomicClock),当执行 delete ptk的时候,派生类的base class成分会被删除,但是derived成分却未被销毁,因为derived class 的析构函数没有被调用。

解决方法: 给 base class一个virtual析构函数。(用一个基类指针删除一个派生类对象时,派生类析构函数会被调用(先调用基类析构,在调用基类析构,与构造函数数顺序相反))


(二)

如果一个class不含virtual函数,通常表示它并不意图做一个base class。当class不企图当做base的class的时候。不要令其析构函数为:vitual。

因为当创建一个含有虚函数的对象的时候,会伴随一个vptr出现。增加了该类的对象在内存中占的大小。

所以:当class 内含有至少一个virtual函数,才把它声明为virtual析构函数。

(三)

标准 string不含任何virtual函数,但有时候程序员会错误的把它当做base class 就出现问题了

class SpecialString : public string {
	...;
};
SpecialString* pss = new SpecialString("Impending Doom");
string* ps;
...
ps = pss;
...
delete ps;
由于string的析构函数不是虚函数,同(一),不能够调用子类的析构函数,造成一个诡异的”局部销毁“对象。
现实中*psde SpecialString资源会泄露,因为SpecialString析构函数没有被调用。

(四)

让class带一个pure virtual 析构函数很便利。(不能被实例化),这样也不必担心析构函数的问题了。

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

AWOV::~AWOV() {}    //定义!不定义的话,当AWOV派生类对象被析构的时候,连接器会报错!


析构函数运作方式:析构函数先被调用,然后每一个base class析构函数被调用。编译器会在AWOV的derived class的析构函数中创建一个对~AWOV调用动作,所以必须为这个函数提供一份定义。不这样,链接器会报错。

请记住:

1 polymorphic(带多台性质的)base classes应该声明一个析构函数。如果class带有任何virtual 函数,它就应该拥有一个virtual析构函数

2 Classes的设计目的如果不是作为base classes使用,或不是为了具备多态性,就不该声明virtual析构函数。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值