1.try,catch,throw:
try包含你要防护的代码 ,称为防护块.
防护块如果出现异常,会自动生成异常对象并抛出.
catch捕捉特定的异常,并在其中进行适当处理.
throw可以直接抛出/产生异常,导致控制流程转到catch块.
2.重要观点: C++中异常是用对象来表示的,称为异常对象.
3.基本格式:
try { your code; }
catch(T1 t1) //T1可以是任意类型,int,char...
{ /*T1指定了你要捕捉的异常的类型,t1指定了异常 对象的名称,当有异常抛出,异常对象将被复制到t1
中,这样你就可以在本处理块中使用该对象,获取相关信息,进行适当处理;*/}
catch(...) //...是捕捉任意类型的异常.
/*某个catch执行完,就跳转到这里继续执行. 在没有使用C++异常处理的情况下,如果在此之前出现异常,则异常点以下的其他代码不会被执行从而造成问题.请考虑在这里放置:
delete pobj1;如果不使用用try,catch机制,内存泄漏是必然的,因为出现问题后,执行流程无法跳转到这里. */
/*说明: try{}之后可以跟任意个catch块. 发生异常后,会生成临时的异常对象,进行一些自动处理之后,程序 流程跳转到后面的catch(),逐个检查这些catch(),如果与catch()
中指定的类型一致,则将对象拷贝给catch参数中的对象, 接着执行该catch块中的代码,然后跳过其他所有剩下的catch, 继续执行后续的代码.
上面所说的自动处理指的是堆栈回退,说白了就是为函数中的局部对象调用析构函数,保证这些局部对象行为良好. */
catch()的顺序通常按照:从特殊到一般的顺序: catch(Tsub o){} catch(Tbase o){} catch(...){}
如果第一个catch为catch(Tbase){},则它将捕捉其所有派生类的 异常对象.
如果第一个catch为catch(...){},则其后的所有catch永远不可能 被执行. 重新抛出异常:
从上面的处理机制可以看到,只有一个catch可能被执行, 如果一个catch被执行,其他后续的catch就会被跳过了.
有时候一个catch中可能无法完成异常的全部处理,需要将 异常提交给更高的层,以期望得到处理.重新抛出异常实现 了这种可能性. 语法: throw
; 空的throw语句,只能在catch中使用.
它重新抛出异常对象,其外层的catch可能可以捕捉这个重新抛出的异常并做适当处理.
---------------------------------------------------------------------------------------------------------
1、基础介绍 try { //程序中抛出异常 throw value; } catch(valuetype v) { //例外处理程序段 }
语法小结:throw抛出值,catch接受,当然,throw必须在“try语句块”中才有效。
2、深入throw:
(i)、程序接受到throw语句后就会自动调用析构器,把该域(try后的括号内)对象clean up,然后再进
入catch语句(如果在循环体中就退出循环)。
这种机制会引起一些致命的错误,比如,当“类”有指针成员变量时,在 “类的构建器
”中的throw语句引起的退出,会导致这个指针所指向的对象没有被析构。解决方法:把指针改为类就行了,比如模板类来代替指针,在模板类的内部设置一个析构函数。
(ii)、语句“throw;”抛出一个无法被捕获的异常,即使是catch(...)也不能捕捉到,这时进入终止函数。
3、深入catch:
一般的catch出现的形式是: try{} catch(except1&){} catch(except2&){}
catch(...){} //接受所有异常 一般都写成引用(except1&),原因很简单,效率。
问题a:抛出异常,但是catch不到异常怎么办?在catch没有捕获到匹配的异常的时候,会调用默认的终止函数。可以调用set_terminate()来设置终止函数,参数是一个函数指针,类型是:void
(*terminate)()。
4、try一个函数体,形式如下 void fun(type1,type2) try----try放在函数体后 { 函数定义 }
catch(typeX){} 这个用法的效果就相当于: void fun() { try{函数定义} }
5、throw一个函数体,形式如下: void fun (); // 能抛出任何类型的异常 void fun ()
throw(except1,except2,except3)
// 后面括号里面是一个异常参数表,本例中只能抛出这3中异常,如 void fun () throw() //
参数表为空,不能抛出异常
假设fun()中抛出了一个不在“异常参数表”中的异常,会怎么样?调用set_terminate()中设定的终止函数。然而,这只是表面现象,实际上是调用默认的unexpected()函数,然而这个默认的
unexpected()调用了set_terminate()中设定的终止函数。可以用set_unexpected()来设置unexpected,
就像set_terminate()一样的用法,但是在设定了新的“unexpected()”之后,就不会再调用set_terminater中设定的终止函数了。