在C++的发展过程中,为了实际的需要,引入了异常处理机制。程序中常见的错误:语法错误和运行错误,语法错误一般都是在编译时候发现的,编译器基本上都会报出错误的具体位置,因此这类错误一般都是比较好修改,运行错误一般不容易进行调试,比如说,程序崩溃(一般是由于栈溢出),运行结果错误(一般是算法的逻辑结构有问题)、程序非正常终止等现象。C++中引入异常处理(对运行时出现的差错进行处理),能够极大地提高程序的容错能力。
C++处理异常是利用try(检查)、throw(抛出)、catch(捕捉)三部分来进行处理的,把有可能出现异常的代码放到try块中,throw用来抛出一个异常信息,catch的参数一般为抛出的信息类型,如果抛出的类型和catch捕捉的类型相同时候,则就进行对应的异常处理。
下面是一个异常处理的例子:
#include <iostream> using namespace std; #include <math.h> /*定义计算三角形面积的函数(利用海伦公式S = sqrt(q*(q - a)*(q - b)*(q - c)),其中q = (a+b+c)/2)满足三角形的条件:a+b>c a+c>b b+c>a(a,b,c都大于0) */ double triangle(double a, double b, double c) { double q = (a + b + c) / 2; if (a + b <= c || a + c <= b || b + c <= a) //a,b,c这三个长度不能构成三角形 { throw a; //抛出异常 } return sqrt(q * (q - a) * (q - b) * (q - c)); //求三角形面积 } int main() { double a, b, c; cin >> a >> b >> c; try //检查是否出现异常,异常出现在两个方面,一是a,b,c中有可能为负数,或者两边之和不大于第三边 { while (a > 0 && b > 0 && c > 0) { cout << triangle(a, b, c) << endl; cin >> a >> b >> c; } } catch (double) //捕捉异常并处理 { cout << a << " " << b << " " << c << "this is not triangle!" << endl; } system("pause"); return 0; }
在上面的例子中,三角形的三边长度有可能不满足构成三角形的条件,会发生异常,try块中为可能发生异常的代码,在triangle函数中,对三边的长度进行条件的判断,如果不满足,则将异常进行抛出,这时程序会返回主调函数中寻找对应的catch块,上面的throw a;a的数据类型为double类型,main函数中catch进行捕捉的类型也为double类型,两者相匹配,就执行catch块中的处理代码,然后程序不会返回被调用函数抛出的位置,而是直接执行catch后面的代码。
注意:
(1)try块中的代码不会影响原来执行的顺序,如果try中没有发生异常就会不执行catch块中的代码,而直接执行catch之后的代码。若出现异常,对异常进行抛出,流程会立即离开本函数,返回上一级的函数,则不会执行本函数throw后面的代码。
(2)流程返回到上一级函数时,系统会寻找与之匹配的catch块,进而执行。执行完catch块中的代码,紧接着执行catch块后面的代码,直到程序结束。
(3)被检测的部分必须放在try块中,否则会不起作用。catch块不能够单独使用,但是try块可以单独使用,但是只进行检查,而不进行错误处理。try和catch块中必须使用花括号括起来,哪怕块中只有一个语句。一个程序中只能有一个try块,但可以有多个catch块,可以进行多个问题的处理。catch只会检查参数的类型,不检查参数的值。
(4)若catch(doube b){}; 则是将参数的double类型和throw a;的类型进行比较,然后将a的值赋值给b,即就是b=a;
若catch(...){}; 则是不论什么类型,都会执行catch块中的代码。一般这样的catch会放在程序的最后,对于一些意想不到的异常进行处理,如果放在最开始则后面的catch就不会被执行。
(5)try-catch可以和throw在同一个函数中,也可以不在同一个函数中,若不在一个函数中,它们的catch执行满足下图的关系:
(6)如果throw的异常信息没有找到与之相匹配的catch,系统会自动调用一个系统函数terminate函数,使得程序停止运行。