• 10异常处理


    在编写软件时,不仅要有正确性,而且应该具有容错能力。这里就要引入异常处理了。

    1、异常处理的基本思想

    程序运行中的有些错误可以预料但不可避免的,如内存空间不足、硬盘上的文件被移动等由系统运行环境造成的错误。这时要力争做到允许用户排除环境错误,继续运行程序;至少要给出适当的提示信息。这就是异常处理程序的任务。

    c++的异常处理机制使得异常的引发和处理不必在同一函数中,这样底层的函数可以着重解决具体问题,而不必过多地考虑对异常的处理。上层调用者可以在适当的位置设计对不同类型异常的处理。

    2、c++异常处理的实现

    c++语言提供对处理异常情况的内部支持。try、throw和catch语句就是c++语言中用于实现异常处理的机制。

    有了c++异常处理,程序可以向更高的执行上下文传递意想不到的事件,从而使程序能更好地从这些异常事件中恢复过来。

    2.1异常处理的语法

    throw表达式语法:

    throw  表达式

    try块语法:

    try

      复合语句

    catch(异常类型声明)

         复合语句

    catch(异常类型声明)

      复合语句

      ...

    如果某段程序中发现了自己不能处理的异常,就可以使用throw表达式抛掷这个异常,将它抛掷给调用者。

    throw的操作数表示异常类型,语法上与return语句的操作数相似,如果程序中有多处要抛掷异常,应该用不同的操作数类型来相互区别,操作数的值不能用来区别不同的异常。

    try子句后的复合语句是代码的保护段。如果预料某段程序代码(或对某个函数的调用)有可能发生异常,就将它放在try子句之后。如果这段代码(或被调用函数)运行时真的遇到异常情况,其中的throw表达式就会抛掷这个异常。

    catch子句后的复合语句是异常处理程序,“捕获”由throw表达式抛掷的异常。异常类型声明部分致命了子句处理的异常的类型,它与函数的形参是类似的,可以是某个类型的值,也可以是引用。类型可以是任何有效的数据类型,包括c++的类。

    当异常被抛掷以后,catch子句便依次被检查,若某个catch子句的异常类型声明与被抛掷的异常类型一致,则执行该段异常处理程序。如果异常类型声明是一个省略号(...),catch子句便处理任何类型的异常。这段处理程序必须是try块的最后一段处理程序。

    异常处理的执行过程如下:

    1)控制通过正常的顺序执行到达try语句,然后执行try块内的保护段。

    2)如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从异常被抛掷的try块后跟随的最后一个catch子句后面的语句继续执行下去。

    3)如果在保护段执行期间或在保护段调用的任何函数中(直接或间接的调用)有异常被抛掷,则通过throw操作创建一个异常对象(这隐含指可能包含一个拷贝构造函数)。在这一点,编译器在能够处理抛掷类型的异常的更高执行上下文中寻找一个catch子句(或一个能处理任何类型异常的catch处理程序)。catch处理程序按其在try块后出现的顺序被检查。如果没有找到适合的处理程序,则继续检查外层的try块。此处理继续下去直到最外层封闭try块被检查完。

    4)如果匹配的处理程序未找到,则运行函数terminate将被自动调用,而函数terminate的默认功能是调用abort终止程序。

    5)如果找到了一个匹配的catch处理程序,catch处理程序被执行,接下来程序跳转到跟随在最后的处理程序之后的语句。

    例子:

    #include<iostream>
    using namespace std;
    int Div(int x,int y);
    int main()
    {
     try
     {
      cout << "5/2=" << Div(5, 2) << endl;
      cout << "8/0=" << Div(8, 0) << endl;
      cout << "7/1=" << Div(7, 1) << endl;
     }
     catch (int)
     {
      cout << "except of deviding zero. ";
     }
     cout << "this is ok, ";
     getchar();
     getchar();
    }
    int Div(int x, int y)
    {
     if (y == 0)
      throw y;
     return x / y;
    }

    异常被抛掷后,在main()函数中被捕获,异常处理程序输出有关信息后,程序流程跳转到主函数的最后一条语句,输出this is ok.而函数Div中的下列语句没有被执行:

      cout << "7/1=" << Div(7, 1) << endl;

    catch处理程序的出现顺序很重要,因为在一个try块中,异常处理程序是按照它出现的次序被检查的。只要找到一个匹配的异常类型,后面的异常处理都将被忽略。

    2.2异常接口声明

    为了加强程序的可读性,使函数的用户能够方便地知道所使用的函数会抛掷那些异常,可以在函数的声明中列出这个函数可能抛掷的所有异常类型,例如:

    void fun() throw(A,B,C,D);

    这表明函数fun()能够且只能够抛掷类型A,B,C,D及其子类型的异常。

    如果在函数的声明中没有包括异常接口声明,则此函数可以抛掷任何类型的异常,例如:

    void fun();

    一个不抛掷任何类型异常的函数可以进行如下形式的声明:

    void fun() throw();

  • 相关阅读:
    JavaEE三层架构
    请求重定向
    响应的中文乱码问题
    Apache的ServerAlias的作用
    bootstrap 常用class
    linux 退出当前命令的编辑
    硬链接和软链接
    ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry ’1′ for key ‘PRIMARY’
    ie浏览器许多图片放在一起会有间隙
    Could not initialize class utils.JdbcUtils
  • 原文地址:https://www.cnblogs.com/gary-guo/p/6336879.html
Copyright © 2020-2023  润新知