现在的位置: 首页 > 综合 > 正文

二十一天学通C++之异常处理机制

2013年12月01日 ⁄ 综合 ⁄ 共 2617字 ⁄ 字号 评论关闭
异常处理机制
本人节选自《21天学通C++》一书

    C++并不是第一个对结构化运行期错误处理进行支持的语言。早在20世纪60年代,PL/1就提供了一种内建的异常处理机制;Ada也在20世纪80年代提供了自己的异常处理,而C++是在1989年时才有了异常处理机制。但是,C++的异常处理是独一无二的,并且其已经作为了一种模型出现在一些新产生的语言之中。

提示:C++异常处理机制是一个用来有效地处理运行错误的非常强大且灵活的工具,它提供了更多的弹性、安全性和稳固性,克服了传统方法所带来的问题。
事实上,C++中的异常处理机制是一种把控制权从异常发生的地点转移到一个匹配的处理函数或功能块的机制。其中,异常可以是内建数据类型变量,也可以是对象。一般来说,异常处理机制包括4个部分。
    try语句块:即一个定义异常的语句块。
    catch语句块:即一个或多个和try语句块相关的处理,它们放在catch语句块中。
    throw表达式:即抛出异常语句。
    异常本身。
一般来说,try语句块包含可能抛出异常的代码。例如,下列语句可能引发内存空间溢出的异常,其就包含在try语句中。
try
{
    int * p = new int[1000000];
}
一个try语句块后面将跟有一个或多个catch语句,其中,每一个catch语句可以处理不同类型的异常。例如:
try
{
    int * p = new int[1000000];
    //...
}
catch(std::bad_alloc& )                            //内存空间不够,分配内存失败
{
}
catch (std::bad_cast&)                            //转型失败,分配内存失败
{
}
catch语句块仅仅被在try语句块中的throw表达式及函数所调用。其中,throw表达式包括一个关键字throw及相关参数。例如:
try
{
    throw 5;
}
catch(int n)
{
}
读者需要注意的是,throw表达式和返回语句很相似。此外,throw语句可以没有操作数,其格式如下所示:
throw;

注意:一般来说,如果目前没有异常被处理,那么执行一个没有操作数的throw语句后,编译系统将会调用terminate()函数结束程序。
当一个异常被抛出后,C++运行机制首先在当前的作用域寻找合适的处理catch语句块。如果不存在这样一个处理,那么将会离开当前的作用域,进入更外围的一层继续寻找。这个过程不断地进行下去直到合适的处理被找到为止。此时堆栈已经被解开,并且所有的局部对象被销毁。如果始终都没有找到合适的处理,那么程序将会终止。
【范例20-6】求一元二次方程的实根,要求加上异常处理,判断b*b-4*a*c是否大于0,成立则求两个实根,否则要求重新输入,实现代码如代码清单20-6所示。
代码清单20-6
1    #include <iostream>
2    #include <math.h>                                    //包含头文件
3    using namespace std;                                //使用命名空间
4    double sqrt_delta(double d)                        //定义函数
5    {
6        if(d < 0)
7            throw 1;                                    //抛出异常
8        return sqrt(d);                                //返回平方根值
9    }
10    double delta(double a, double b, double c)            //定义函数
11    {
12        double d = b * b - 4 * a * c;
13        return sqrt_delta(d);                            //调用sqrt_delta()函数
14    }
15    void main()
16    {
17        double a, b, c;
18        cout << "please input a, b, c" << endl;
19        cin >> a >> b >> c;                            //接收输入
20        while(true)                                    //循环
21        {
22            try                                        //定义异常
23            {
24                double d = delta(a, b, c);                //调用函数
25                cout << "x1: " << (d - b) / (2 * a);
26                cout << endl;
27                cout << "x2: " << -(b + d) / (2 * a);
28                cout << endl;
29                break;                                //跳出循环
30            }
31            catch(int)                                //定义异常处理
32            {
33                cout << "delta < 0, please reenter a, b, c.";
                                                //重新输入系数
34                cin >> a >> b >> c;
35            }
36        }
37    }
【运行结果】在Visual C++中新建一个【C++ Source File】文件,输入上述的代码,编译无误后运行。
【范例解析】上述范例实现了对于用户输入的一元二次方程系数的判断,由于只有方程的系数符合b*b-4*a*c>0的条件时才有实根,所以上述代码中的sqrt_delta ()函数中包含了异常定义。在上述代码的第31~35行中的catch语句块中包含了对该异常的处理。

提示:catch语句后的参数(即数据类型)需要与throw语句后的表达式数据类型相同。如上述代码中第7行throw语句后的表达式为1,

抱歉!评论已关闭.