1.异常机制的语法
try {
try-fields //我们程序执行要实现某种功能所必需的语句
throw exception-object;//利用条件判断,当某种条件满足时抛出异常表达式
}
catch (exception-[object | pointer | reference] e) { //捕获异常并进行异常处理,不同的异常表达式类型需要不同的catch块,
catch-fields
}
catch (...) { //捕获异常并进行异常处理,这里面的...是可以捕捉任意类型的异常
catch-fields
}。
例1:除法运算过程中的除数为零的判断。
没有异常处理的程序:
带异常处理的程序:
2.异常机制分析
★try:诊断异常代码;
try{
//可能出现异常的情况
}
☆可能出现异常的三种情况:
①可执行语句;②一个函数调用;③一个函数调用另一个函数;
★throw:抛出错误信息;
判断条件检查
条件满足 throw 参数(只有一个,可以是任何类型,甚至是一个对象)
例:
if(分母==0){
throw 参数(只有一个,可以是任何类型,甚至是一个对象)
}
★catch:捕获异常信息;
catch(参数类型参数)//只能一个参数,形参可以被省略,但省略后不能输出异常信息,依然可以捕获;
{ 异常处理 }
注意:catch块不能访问try块里面定义的临时变量。
★注意:如果throw抛出了异常,异常类型如果与catch块后面的类型匹配,catch块内的代码将会被执行,在try语句后面可以有多个catch块,程序会寻找第一个相匹配的catch块,实行catch块的语句代码,然后跳到最后一个catch块的下一行代码,如果没有匹配的catch块,则异常返回上一层try-catch语句,如果没有相应的catch发现,程序将会终结。
★try-throw-catch的三种写法:
//第一种:(操作放在try块中进行判断)
//第二种:(把操作放到函数体中判断并实现)
//第三种:函数嵌套
函数嵌套的异常捕捉例子:
3.异常处理的问题------栈展开(Stack unwinding):
★定义:如果一个函数里产生异常,那么这个函数将会被终结,并且本地变量(栈上的变量)会被释放。但是如果有指针且动态分配了内存,那么栈上的指针将会被释放,而指针指向的堆内存没有被释放,这时会发生内存泄漏。在这种情况下,为了避免内存泄漏,必须把指针抛给它的上一层调用者,让它来释放这块堆内存。我们可以把这个指针封装到一个错误消息类里面去,然后抛出这个类的对象(构造函数构造的临时对象),为了避免临时对象的生成,我们在catch块里用这个类的引用做参数。
例:
func(){
int a=5; //在栈上声明的;
int b=8; //在栈上声明的;
char* p=new char[100] //p在栈上,p指向的内存在堆上;
//throw "exception"; //会发生内存泄漏;
...
...
}
▲为了避免内存泄露,我们需要将指针抛出。我们把指针封装在一个错误类里面,然后把对象抛出,为了避免拷贝构造,我们传一个对象的引用。
例:
▌不捕获异常(Uncaught exception):
★定义:如果一个异常没有被catch住,或者没有写catch块,这种情况就叫不捕获异常。如果一个异常没有被捕获住,则会终结(terminate)函数。
例:
重设异常的两个函数:From MSDN
set_terminate():Installs your own termination routine to be called by terminate.
set_new_handler( ):Installs a user function that is to be called when operator new fails in its attempt to allocate memory.
new_handler set_new_handler(new_handler _Pnew);
例子: