学科分类
目录
C++基础

重抛异常

若某个异常在处理过程中发现需要更外层的结构对它进行处理,则可以通过在catch结构中调用throw重新抛出异常,将当前异常传递到外部的try-catch结构中,这样就允许多个处理程序访问该异常。重抛异常时只能从catch语句块或从catch块中的调用函数中完成,该异常将不会被同一个catch捕捉,而是传递到外层的try-catch结构中。

除了可以采用普通抛出异常的方式重抛异常,还可单独使用throw关键字完成异常重抛。下面分别介绍这两种重抛异常的方式。

1、采用普通方式重抛异常

和前面介绍的抛出异常的语法相同,在catch块中可以采用“throw 异常值;”的方式重抛异常。

接下来通过一个案例来说明如何通过普通方式重抛异常,如例1所示。

例1

 1    #include <iostream>
 2    #include <string>
 3    using namespace std;
 4    int int_div(int a, int b)                                //实现整数相除的函数
 5    {
 6        if (b == 0){
 7            throw 0;
 8        }
 9        return a / b;
 10    }
 11    void exception_handler(int n1, int n2)
 12    {
 13        try{
 14            cout << "Maybe exception code:" << endl;     
 15            cout << n1 << "/" << n2 << " = " 
 16                   << int_div(n1, n2) << endl;               //除数非零显示相除结果
 17            cout << "in try, after div!" << endl;
 18        }
 19        catch (int n)                                          //捕捉参数为整型的异常
 20        {
 21            cout << "exception:div " 
 22                   << n << "!" << endl;                       //异常处理代码
 23            throw n;                                           //重新抛出异常  
 24        }
 25    }
 26    int main()
 27    {
 28        int int_n1, int_n2;                                  //定义两个整型变量
 29        
 30        while (1){                                             //循环多次读取数据,完成相除操作
 31            cout << "Please input two integers:";        
 32            cin >> int_n1 >> int_n2;                        
 33        
 34            try{
 35                exception_handler(int_n1, int_n2);
 36            }
 37            catch (int)
 38            {
 39                cout << "outter try-catch!" << endl;    //接收第23行重抛的异常
 40            }
 41        }
 42        return 0;
 43    }

若除数为0,程序运行结果如图1所示。

图1 例1运行结果

例1仍然完成的是除零异常的检测及捕捉。第11-25行的exception_handler()函数中的try-catch结构用于检测及捕捉除零异常,catch结构捕捉异常后,代码第23行又重新抛出该异常,则代码第34-40行的外层try-catch结构会捕捉该异常进行处理。

2、采用标准语法重抛异常

对于重抛异常,除了和原来相同的语法形式之外,还可使用标准语法形式:

throw;  //throw后没有异常值或异常对象

若抛出的异常是类对象,则通常采用标准语法,例如定义异常类exception的派生类derive_exception,代码如下所示:

class derive_exception: public exception
{
    …
};

在内层try结构中抛出派生类异常:

try
{
  try
  {
​    …
​    throw derive_exception();           //抛出异常派生类对象
  }
  catch (const exception &e)             //使用基类引用作为catch参数
  {
​    cout << “Can not handle the exception” << endl;
​    throw e;                     //重抛基类对象异常//throw;                     //采用标准语法重抛异常
  }
}
catch (…)                        //处理异常
{
  …
  cout << “Handle exception” << endl;
}

上述代码中,内层的try结构内抛出了派生类对象异常,但接收异常的catch结构却使用了基类形参,catch结构中又将异常按照基类类型重新抛出,则会导致原有派生类异常对象的部分信息丢失,解决办法是,采用异常重抛的标准语法格式重抛异常。

另外还有一点需要说明的是,采用标准语法抛出的是当前捕获的异常,而不是新的拷贝;采用“throw e;”方式抛出异常需要进行对象拷贝,拷贝动作带来了对象的构造与析构,会降低工作效率。

点击此处
隐藏目录