一、抛出异常
异常处理机制两个主要成分:
- 异常的鉴定与发出;
- 异常的处理方式。
C++通过throw表达式产生异常:
cpp
inline void Triangular_iterator::
check_integrity()
{
if(_index>=Triangular::max_elems)
{
throw iterator_overflow(_index, Triangular::_max_elems);
if(_index >= Triangular::elems.size())
{
Triangular::gen_elemts(_index+1);
}
}
}
//换个方式:明确指出被抛出的对象名称
if(_index>=Triangular::max_elems)
{
iterator_overflow ex(_index,Triangular::_max_elems);
throw ex;
}
异常对象
最简单的异常对象可以设计为:整数或字符串:
cpp
throw 42;
throw "panic:no buffer!";
异常类
大部分时候,被抛出的异常都属于特定的异常类:
cpp
class iterator_overflow{
public:
iterator_overflow(int index,int max):_index(index),_max(max){}
int index(){return _index;}
int max(){return _max;}
void what_happened(ostream &os=cerr)
{
os<<"Internal error:current index "<<_index
<<" exceeds maximum bound: "<<_max;
}
private:
int _index;
int _max;
};
二、捕获异常
catch子句
由三部分组成:
- 关键字catch;
- 小括号内的一个类型或对象;
- 大括号内的一组语句(用以处理异常)。
cpp
extern void log_message(const char*);
extern string err_messages[];
extern ostream log_file;
bool some_function()
{
bool status = true;
catch(int errno)
{
log_message(err_messages[errno];
status = false;
}
catch(const char *str)
{
log_message(str);
status = false;
}
catch(iterator_overfloww &iof)
{
iof.what_happened(log_file);
status = false;
}
return status;
}
//逐个处理
throw 42;
throw "panic:no buffer!";
throw iterator_overflow(_index,Triangular::_max_elems);
有时候我们可能无法完成异常的完整处理。在记录信息之外,我们或许需要重新抛出异常,以寻求其他catch子句的协助:
cpp
catch(iterator_overflow &iof)
{
log_message(iof.what_happened());
//重新抛出异常,另一个catch子句来接手处理
throw;//甚至只可以出现在catch子句中
}
捕获任何类型的异常:catch(...)
cpp
catch(...)
{
log_message("exception of unknown type");
//清理后退出
}
三、提炼异常
try块
- try语句块用来处理异常,try语句块以关键字try开始,以一个或多个catch子句结束,try语句块中代码抛出的异常通常会被某个catch子句处理;
- 当函数的try块发生某个异常,但没有相应的catch子句将它捕获,此函数便会转到terminate的标准库函数,terminate会终止当前进程的执行,由异常处理机制接管,沿着"函数调用链"一路回溯,搜寻符合条件的catch子句。
cpp
bool has_elem(Triangular_iterator first, Triangular_iterator last, int elem)
{
bool status = true;
try
{
while(first != last)
{
if(*first == elem)
{
return status;
}
++first;
}
}
catch(iterator_overflow &iof)
{
log_message(iof.what_happened());
iog_message("check if iterators address same container");
}
//try块内的程序代码执行时,如果有任何异常抛出,
//只捕获其中类型为iterator_overflow的异常。
status = false;
return status;
}
四、局部资源管理
函数执行之初所分配的资源不一定最终会被释放掉。
解决:资源管理的手法(在初始化阶段即进行资源请求)
cpp
#include<memory>
void f()
{
auto_ptr<int>p(new int);
MutexLock m1(m);
process(p);
//p和m1的析构函数在此被悄悄调用
}
auto_ptr
标准类模板:自动删除通过new表达式分配的对象。
auto_ptr将*运算符和->运算符予以重载,方式类似迭代器类那样,我们得以像使用一般指针一样地使用auto_ptr对象:
cpp
auto_ptr<string>aps(new string("vermeer"));
string *ps=new string("vermmer");
if((aps->size()==ps->size())&&(*aps==*ps))
//...
五、标准异常
自己编写的异常类继承给exception基类:
- 所有的异常类都有一个
what()
方法,返回const char*
类型,描述异常信息; - 可被任何"打算捕获抽象基类exception"的程序代码所捕获。