• C++:异常的处理


                          6.4 异常处理
    程序中常见的错误分为两大类:编译时期的错误和运行时期的错误。

    编译时期的错误比较简单容易发现:主要是语法错误,如关键字拼写错误、缺分号、括号不匹配等
    运行时期的错误比较难发现,甚至是不可预料的:如算法出错、内存空间不足、角标越界、文件无法打开等

    处理异常有两种方式:传统的异常处理方法、系统异常处理机制。

    传统异常处理方法特点:是采用判断和分支语句类实现,适合满足小型的应用程序。
    系统异常处理机制特点:通过检测、抛出并捕获异常来实现,适合各种大型应用程序

    //例6.10  传统的异常处理方法举例

    #include<iostream>
    using namespace std;
    inline int DIV(int x,int y);
    int main()
    {
     cout<<"7/3="<<DIV(7,3)<<endl;
     cout<<"5/0="<<DIV(5,0)<<endl;
     return 0;
    } 
    inline int DIV(int x,int y)
    {
     if(y==0)
      {
        cout<<"除数为0,错误!"<<endl;
        exit(0);
      }
     return x/y;
    }

    6.4.2 异常处理的方法
    C++处理异常的办法是:如果在执行一个函数过程中出现异常,可以不在本函数中立即处理,而是发出一个信息,传给它的上一级(即调用函数)来解决,如果上一级也不能处理,就再传其上一级,由上一级处理,如此逐级上传,如果到最高一级还无法处理,运行系统一般会自动调用系统函数terminate,由它调用abort终止程序。

    这样的处理方法使得异常的引发和处理机制分离,而不是有同一个函数完成。这样的做法的好处是使底层函数(被调用函数)着重用于解决实际任务,而不必过多的考虑对异常的处理,以减轻底层函数的负担,而把处理异常的任务移到上层去处理。


    C++处理异常的机制是由检查、抛出和捕获3个部分组成,分别由3中语句来完成;try(检查)、
    throw(抛出)、catch(捕获)

    1.异常的抛出
    抛出异常使用throw语句,其格式如下:
    throw 表达式;

    如果在某段程序中发现了异常,就可以使用throw语句来抛出异常给调用者,该异常由与之匹配的catch语句来捕获。throw语句中的"表达式”是可以抛出的异常类型,异常类型由表达式的类型来表示。例如上例中的异常处理:

    inline int DIV(int x,int y)
         {
           if(y==0)
             throw y;            //抛出异常,当除数为0时,语句throw将抛出int型异常 
           return x/y;  
         } 
         
         由于变量y的类型是int型,所以当除数为0时语句throw将抛出int型异常

    2.异常的检查与捕获
    异常的检查try语句与捕获catch语句的格式如下:

    try
        {
          被检查的复合语句 
        }  
        catch(异常类型声明 1)
        {
          进行异常处理的复合语句 1 
        }
        catch(异常类型声明 2)
        {
          进行异常处理的复合语句 2 
        }
        ......    
        catch(异常类型声明 n)
        {
          进行异常处理的复合语句 n 
        }

    例如上述例子的异常检查与捕获:

    try                                       //检查异常 
        {
           cout<<"7/3="<<DIV(7,3)<<endl;          //被检查的复合语句 
           cout<<"5/0="<<DIV(5,0)<<endl;
        }
        catch(int)                                  //捕获异常,异常类型为int类型
        {
           cout<<"除数为0,错误!"<<endl;           //进行异常处理的复合语句 
        }  

    //例6.11 处理除数为0异常的程序。

    #include<iostream>
    using namespace std;
    inline int DIV(int x,int y);
    int main()
    {
     try
     {
      cout<<"7/3="<<DIV(7,3)<<endl;
      cout<<"5/0="<<DIV(5,0)<<endl;
     }
     catch(int i) 
     {
      cout<<"i="<<i<<endl;    
      cout<<"除数为0,错误!"<<endl;
      cout<<"over
    ";
     }
     return 0;
    } 
    inline int DIV(int x,int y)
    {
     if(y==0)
       throw y;
     return x/y;
    }

    程序运行结果是:
    7/3=2
    除数为0,错误!
    over

    在本例中,进行异常处理的方法如下:
    (1)首先将需要检查,也是容易引起异常的语句或程序段放在try块的花括号中。
    (2)如果在执行try语句块内的复合语句过程中没有发生异常,则catch子句不起作用,继续转到catch子句后面的语句继续进行。

    (3)如果在执行try块内的复合语句(或被调用函数)过程中发生异常,则throw语句抛出一个异常信息。

    (4)throw抛出的异常信息传到try_catch结构,系统寻找与之匹配的catch子句。
    (5)执行异常处理语句后,程序继续执行catch子句后的语句。

    说明:
    (1)被检测的语句或程序段必须放在try块中,否则不起作用。
    (2)try和catch块中必须有用花括号括起来的复合语句,即使花括号内只有一个语句也不能省略花括号。
    (3)一个try_catch结构中只能有一个try块,但却可以有多个catch块,以便与不同的异常信息匹配。catch后面的括号中,一般只写异常信息的类型名。

    (4)如果在catch语句中没有指定异常信息的类型,而是采用了三点删节点"...",则表示它可以捕获任何类型的异常信息。

    (5)在某种情况下,在throw语句中可以不包括表达式,如;throw;此时它将当前正在处理的异常信息再次抛出,给起上一层的catch块处理。

    (6)C++中,一旦抛出一个异常,而程序又不捕获的话,那么系统就调用系统函数terminate,由它调用abort终止程序。

    //例6.12 有多个catch块的异常处理程序。

    #include<iostream>
    using namespace std;
    int main()
    {
     double a=2.3;    
     try
     {
      throw a;
     }
     catch(int)
     {
      cout<<"异常发生!整数型!"<<endl; 
     }
     catch(double)
     {
      cout<<"异常发生!双精度型!"<<endl; 
     } 
     cout<<"end"<<endl;
     return 0; 
    }
    
    /*
    程序运行结果是:
    异常发生!双精度型!
    end 
    */

    //例 6.13 有删节点的异常处理程序。

    #include<iostream>
    using namespace std;
    void func(int x)
    {
     if(x)
       throw x;
    } 
    int main()
    {    
     try
     {
      func(5);
      cout<<"No here!"<<endl;
     }
     catch(...)
     {
      cout<<"异常发生!任意类型!"<<endl; 
     }
     cout<<"end"<<endl;
     return 0; 
    }
    /*
    程序运行结果是:
    异常发生!任意类型!
    end
    */ 
  • 相关阅读:
    pytest临时文件
    djangoclassmeta说明
    python方法
    字符串统计个数2
    python之fixture作用域
    djangomodel在已有model同步添加新的字段
    将 Access 数据库 转换到Sql Server 中
    .net 实现条码
    条码打印异步调用
    日期控件datepicker 只能选指定段日期案例
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/4912777.html
Copyright © 2020-2023  润新知