异常安全议题及技术
在现代C++程序设计中,对异常安全(exception safety)议题一无所知却想写出健壮的代码,这无异于痴人说梦。的确如此。
如果你在使用C++标准库,哪怕只是用到了new,你也得为异常做好准备。本章建立在Exceptional C++相应章节的基础上,并讨论了新的议题及相关技术,例如:std::uncaught_exception()是什么?它能帮助你写出更健壮的代码吗?异常安全影响到类的设计吗?或者,它可以只是作为事后的改进手段来使用吗?为什么要用管理者对象(manager objects)来封装资源所有权?为什么“资源获取才是初始化”的认识对于编写安全代码如此重要?
但首先还是让我们来热身一下,看一个有关异常安全的基本话题;这个话题对以下非常重要的C++基本概念进行了说明,并剖析了其更深层的含义:构造具有什么含义?什么是对象的生命期?
|
条款17:构造函数失败,之一: 对象生命期 |
难度:4 |
|
确切地说,构造函数产生异常时到底会发生些什么?如果异常来自子对象或成员对象的构造期间,情况又会怎样? | |
1. 请看下面这个类:
// 例17-1
//
class C : private A
{
B b_;
};
在C的构造函数中,如何捕捉从基类子对象(例如A)或成员对象(例如b_)的构造函数中抛出的异常?
2. 请看下面的代码:
// 例17-2
//
{
Parrot p;
}
这个对象的生命期何时开始?何时结束?在对象的生命期之外,对象处于什么状态?最后,如果它的构造函数抛出了一个异常,那将意味着什么?
|
解答 |
在C++中增加function try block这一特性后,函数可以捕获异常的范围稍微增大了一些。本条款的内容涉及:
·在C++中,对象构造与构造失败的含义;
·基类或成员子对象的构造函数抛出异常时,function try block可用于转化(而非抑制)这个异常。
方便起见,除非特别指出,本条款中的“成员”指的是“非静态的类数据成员”。
Function Try Block
1. 请看下面这个类:
// 例17-1
//
class C : private A
{
B b_;
};
在C的构造函数中,如何捕捉从基类子对象(例如A)或成员对象(例如b_)的构造函数中抛出的异常?
这正是function try block的用武之地:
// 例17-1(a): 构造函数的function try block
//
C::C()
try
: A ( /*...*/ ) // 可选的初始化列表
, b_( /*...*/ )
{
}
catch( ... )
{
// 一旦A::A()或B::B()抛出异常,我们会来到这儿
// 如果A::A()成功,然后B::B()抛出异常,
// C++语言将保证,在到达本






