Effective C++条款8,9析构中的异常和虚拟函数



条款8:别让异常逃离析构函数

析构函数的作用就是清理资源等后续工作,一旦这里发生异常就会产生严重后果。所以在编写析构函数时要格外小心。

class Widget{
public:
...
~Widget(){...}
};
void doSomething()
{
std::vector<Widget> v;
...
}

注:vector是STL内的东东,类似于数组,不过更加强大。

那么vector v被销毁时,里面的多个Widget对象也要被销毁。会多次调用~Widget(),如果一旦有连续~Widget()发生异常,那么后续的Widget就会发生内存泄露。所以针对析构函数的设计要小心。那么处理异常我第一个想到的方法就是 try catch。在析构函数本体内利用try catch 语句处理异常,还要注意析构函数内的复旦不要过大,减少发生异常概率,做到以上两点就可以尽量避免以上问题。

条款9:绝不在构造和析构过程中调用virtual函数

这个很奇怪,反正在见到这句话之前,我还真没想过这么做(因为没有见到过,不敢用)。如下

class Transaction{
public:
Transaction();
virtual void logTransaction() const=0;
....
};

尽管我没这么做过,很多人都没这么做过,但是不排除以下可能性的发生

class Transaction{
public:
Transaction()
{init();}
virtual void logTransaction() const=0;
...
private:
void init()
{
...
logTransaction();
}
};


以上两种行为都是不允许的。为何?

若有子类,且构造对象

class BuyTransaction:public Transaction{
public:
virtual void logTransaction() const;
... 
};
BuyTransaction b;

那么我们知道在子类的构造期间的顺序是先构造基类部分(即调用基类构造函数)然后再构造子类。在构造基类时,基类构造函数中的虚拟函数就会运行,并且其还是基类版本。为什么呢?因为在构造基类时,子类的的特有成员还都不存在,此时logTransaction()必定是基类版本。由于纯虚函数,必定会发生错误。即使不是pure virtual,那也可能违背了使用者的原意。同理析构函数析构顺序相反,但结果也是这样。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值