zoukankan      html  css  js  c++  java
  • Visual C++中的异常处理浅析(2)

    2.C++语言异常处理

      2.1 C++异常处理语法

      感谢C++语言的后期改造者们,他们在标准C++语言中专门集成了异常处理的相关语法(与之不同的是,所有的C 标准库异常体系都需要运行库的支持,它不是语言内核支持的)。当然,异常处理被加到程序设计语言中,也是程序语言发展和逐步完善的必然结果。我们看到,C++不是唯一集成异常处理的语言。

      C++的异常处理结构为:

    try
    {
    //可能引发异常的代码
    }
    catch(type_1 e)
    {
    // type_1类型异常处理
    }
    catch(type_2 e)
    {
    // type_2类型异常处理
    }
    catch (...)//会捕获所有未被捕获的异常,必须最后出现
    {
    }

      而异常的抛出方式为使用throw(type e),try、catch和throw都是C++为处理异常而添加的关键字。看看这个例子:

    #include <stdio.h>
    //定义Point结构体(类)
    typedef struct tagPoint
    {
     int x;
     int y;
    } Point;
    //扔出int异常的函数
    static void f(int n)
    {
     throw 1;
    }

    //扔出Point异常的函数
    static void f(Point point)
    {
     Point p;
     p.x = 0;
     p.y = 0;
     throw p;
    }

    int main()
    {
     Point point;
     point.x = 0;
     point.y = 0;

     try
     {
      f(point); //抛出Point异常
      //f(1); //抛出int异常
     }
     catch (int e)
     {
      printf("捕获到int异常:%d\n", e);
     }
     catch (Point e)
     {
      printf("捕获到Point异常:(%d,%d)\n", e.x, e.y);
     }

     return 0;
    }

      函数f定义了两个版本:f(int)和f(Point),分别抛出int和Point异常。当main函数的try{…}中调用f(point)时和f(1)时,分别输出:

      捕获到Point异常:(0,0)

      和

      捕获到int异常:1

      在C++中,throw抛出异常的特点有:

      (1)可以抛出基本数据类型异常,如int和char等;

      (2)可以抛出复杂数据类型异常,如结构体(在C++中结构体也是类)和类;

      (3)C++的异常处理必须由调用者主动检查。一旦抛出异常,而程序不捕获的话,那么abort()函数就会被调用,弹出如图1所示的对话框,程序被终止;

      (4)可以在函数头后加throw([type-ID-list])给出异常规格,声明其能抛出什么类型的异常。type-ID-list是一个可选项,其中包括了一个或多个类型的名字,它们之间以逗号分隔。如果函数没有异常规格指定,则可以抛出任意类型的异常。

      2.2 标准异常

      下面给出了C++提供的一些标准异常:

    namespace std
    {
     //exception派生
     class logic_error; //逻辑错误,在程序运行前可以检测出来

     //logic_error派生
     class domain_error; //违反了前置条件
     class invalid_argument; //指出函数的一个无效参数
     class length_error; //指出有一个超过类型size_t的最大可表现值长度的对象的企图
     class out_of_range; //参数越界
     class bad_cast; //在运行时类型识别中有一个无效的dynamic_cast表达式
     class bad_typeid; //报告在表达试typeid(*p)中有一个空指针p

     //exception派生
     class runtime_error; //运行时错误,仅在程序运行中检测到

     //runtime_error派生
     class range_error; //违反后置条件
     class overflow_error; //报告一个算术溢出
     class bad_alloc; //存储分配错误
    }

      请注意观察上述类的层次结构,可以看出,标准异常都派生自一个公共的基类exception。基类包含必要的多态性函数提供异常描述,可以被重载。下面是exception类的原型:

    class exception
    {
     public:
      exception() throw();
      exception(const exception& rhs) throw();
      exception& operator=(const exception& rhs) throw();
      virtual ~exception() throw();
      virtual const char *what() const throw();
    };

      其中的一个重要函数为what(),它返回一个表示异常的字符串指针。下面我们从exception类派生一个自己的类:

    #include <iostream>
    #include <exception>
    using namespace std;

    class myexception:public exception
    {
     public:
     myexception():exception("一个重载exception的例子")
     {}
    };

    int main()
    {
     try
     {
      throw myexception();
     }
     catch (exception &r) //捕获异常
     {
      cout << "捕获到异常:" << r.what() << endl;
     }
     return 0;
    }

      程序运行,输出:

      捕获到异常:一个重载exception的例子

      一般的,我们直接以基类捕获异常,例如,本例中使用了

    catch (exception &r)

      然后根据基类的多态性进行处理,这是因为基类中的what函数是虚函数。
  • 相关阅读:
    Go基础篇【第2篇】: 内置库模块 fmt
    Go基础篇【第1篇】: 内置库模块 OS
    JavaScript学习基础篇【第1篇】: JavaScript 入门
    Python基础篇【第8篇】: Socket编程(二)SocketServer
    Python基础篇【第7篇】: 面向对象(1)
    APP爬虫之Appium使用
    python操作MongoDB
    MySQL性能调优
    ubuntu16.04中启动anaconda图形化界面
    linux 在命令行中通过conda使用anaconda
  • 原文地址:https://www.cnblogs.com/adylee/p/1233064.html
Copyright © 2011-2022 走看看