一、概念
异常处理的优势:
将程序逻辑&错误处理逻辑混在一起,会降低程序性能。如果没有异常发生,异常处理代码对性能的影响很小。更有效。
异常处理将错误处理从程序执行的“主线”中剥离出来,提高程序的清晰性,增强可修改性。程序员可以处理任何异常——所有异常、某种类型的所有异常 或 一组相关类型的所有异常(即通过继承层次相联系的异常类型)。减少错误的可能性,是程序更健壮。
异常处理必需品:
定义异常类,表示可能出现的问题类型(见代码)
在try代码块中包含代码
try代码块由关键字try以及后面的一对大括号组成,大括号中定义的代码块,就是可能出现异常的代码。try代码块中包含了可能引起异常的语句以及发生异常时应该跳过的语句。(也就是可能引起异常的函数以及没有异常发生时应该执行的语句)
异常可能是由try代码块中的代码直接导致的,也可能是由于调用其它函数导致的,还有可能是由于try代码块中的代码所发起的深层嵌套函数调用所导致的。
定义catch处理器,处理DivideByZeroException异常
异常是由catch处理器处理的,他会捕获并处理异常。在每个try代码块之后,必须至少紧挨着一个catch处理器。每个catch处理器都以关键字catch开始,并在一对圆括号中指定一个异常参数(exception parameter),表示它能够处理的异常的类型(DivideByZeroException)。当try代码块发生异常时,就会执行异常参数的类型与这个异常匹配的那个catch处理器(即catch代码块的类型与被抛出的异常类型准确对应,或者是他的基类)。如果异常参数包含可选的参数名,则catch处理器可以使用这个参数名与catch处理器代码体重被捕获的异常交互(不理解)
catch捕获到异常后通常要干的事:向用户报告错误,在文件中记录日志,从容的终止程序,尝试用其他策略完成这个失败的任务。
catch 以引用的形式捕获异常对象,消除了复制表示被抛出异常对象的开销。
异常处理的终止模型(即程序如何运行)
如果try代码块中的语句产生了异常,则这个try代码块就会立即终止。程序会搜索能够处理这种异常类型的第一个catch处理器。catch到达他的右大括号,异常处理完毕。catch处理器中定义的局部变量(包括它的异常参数)便离开了作用域。程序控制并不返回异常发生的那一抛出点。控制将在try代码块下面的最后一个catch处理器后的第一条语句恢复执行。
如果try代码块没有发现异常,则程序会忽略所有catch处理器,而程序的控制会在这个try代码块下面的最后一个catch处理器之后的第一条语句继续。
如果try代码块产生了异常,但不存在匹配的catch处理器,或者异常发生在try代码块外部的语句里,则包含这条语句的函数会立即终止,程序会尝试在调用函数中找到一个外层try代码块。——堆栈解退(详见后)
何时使用异常处理
异常处理专门用于应付在执行语句时发生的同步错误。常见例子:数组下标越界、算术溢出(即值位于可表示的范围之外)、除零、无效的函数参数以及不成功的内存分配(内存不够)。
异常处理不使用处理与异步事件。例子:磁盘I/O完成、网络消息到达、鼠标单击、键击。这些是与程序的控制流平行的或独立的。
包含常见错误条件的函数,应该返回0或NULL(或其他合适的值),而不是抛出异常。调用这种函数的程序,可以检查函数的返回值,以判断函数调用是否成功。
重抛异常
异常处理器接收到异常时,可能无法处理这个异常,或者只能处理这个异常的一部分。此时,异常处理器可以将异常处理(或者其中的一部分)推送给另一个异常处理器。通过语句:
throw;
重抛异常。不管异常处理其是否能够处理(甚至是部分处理)异常,他都能够重抛这个异常。在他的外面进行进一步处理。下一个try代码块会检测到这个重抛的异常,在后面的catch处理器会尝试处理这个异常。
#include<iostream>
using std::cout;
usign std::endl;
#include<exception>
using std::exception;
// throw ,catch and rethrow exception
void throwException(){ // throw exception and catch it immediately
try{
cout<<" Function throwException throws an exception/n";
throw exception(); // generate exception
}catch( exception &){ // handle exception
没有在这个例子的catch处理器中使用异常参数,因此省略了异常参数名,至指定了要捕获的异常类型
cout<<" Exception handled in function throwException"
<<"/n Function throwException rethrows exception ";
throw; // rethrow exception for further processing
} // end catch
cout<<"This also should not print/n";
} // end function throwException
int main(){
try{ // throw exception
cout<<"/nmain invokes function throwException/n";
throwException();
cout<<"This should not print/n "; } // end try
catch( exception & ){ // handle exception
cout<<" /n/nException handled in main/n";} // end catch
cout<<"Program control continues after catch in main/n";
return 0;
} // end main
二、常见编程错误:
1、try代码块与对应的catch处理器之间,或者在它的几个catch处理器之间放置代码——语法错误
2、每个catch处理器只能有一个参数,如果指定了一个逗号分隔的异常参数表——语法错误
3、在一个try代码块之后的两个不同的catch处理器中捕获同一种类型的异常——逻辑错误
4、在catch处理器的外面执行一条空的throw语句,会导致调用terminate函数,他会放弃异常处理,并立即终止程序。