C++异常

(参阅书籍:C++标准程序库)

标准异常类别

语言本身或标准程序库所抛出的所有异常,都派生自基类exception。这些标准异常类别的分为三类:

  1. 语言本身支持的异常
  2. C++标准程序库发出的异常
  3. 程序作用域(scope of a program)之外发出的异常

分别说明:

语言本身支持的异常-用来支撑某些语言特性:

  1. bad_alloc

    任何使用动态内存的东西(例如所有STL容器)如果无法找到足够内存以满足需求,通常会抛出一个bad_alloc异常。如全局操作符new操作失败会抛出此异常。

  2. bad_cast

    执行期间,当一个加诸于引用的“动态型别转换操作”失败时,dynamic_cast会抛出此异常

  3. bad_typeid

    RTTI(运行期类型识别)过程中,如果交给typeid的参数为0或空指针,typeid会抛出此异常

  4. bad_exception

    发生非预期的异常会抛出该异常,方式:

    • 如果在异常规格中列出bad_exception,那么unexpected()总重新抛出bad_exception异常。

    • 当函数抛出异常规格以外的异常,bad_exception调用:unexpected().

      //example
      class E1;
      class E2;
      void fun() throw(E1)//该函数仅抛出E1类异常
      {
      ...
      throw E1();
      throw E2();//调用unexpected(),该函数又调用terminate()终止程序.
      }

C++标准程序库发出的异常–总派生自logic_error。

逻辑错误包括:违背逻辑前提或违反class的不变性。

  1. invalid_argument-无效参数

    相关知识点:

    bitset:有些程序要处理二进制位的有序集,每个位可能包含的是0(关)或1(开)的值。位是用来保存一组项或条件的yes/no信息(有时也称标志)的简洁方法。标准库提供了bitset类使得处理位集合更容易一些。要使用bitset类就必须要包含相关的头文件。假设使用了std::bitset的using声明:

    #include <bitset>
    using std::bitset;
  2. length_error

  3. out_of_range–参数值不在预期范围内

  4. domain_error–专业领域范畴内的错误

此外,标准程序库的I/O部分提供了ios_base::failure 特殊异常。当数据流由于错误或由于到达文件尾端而发生状态改变时,就可能抛出这个异常。

程序作用域(scope of a program)之外发出的异常

派生自runtime_error。用来指出“不在程序范围内,且不容易回避”的事件。C++标准程序库针对执行期错误提供了三个类:

  1. range_error–内部计算时发生区间错误
  2. overflow_error–算术运算发生上溢位
  3. underflow_error–算术运算发生下溢位

异常类别的头文件

  • < exception>:基础类别exception和bad_exception
  • < new >:bad_alloc
  • < typeinfo >:bad_cast和bad_typeid
  • < ios >:ios_base_failure
  • < stdexcept >:其他异常类别

异常类别的成员

所有标准异常的接口只含有一个成员函数:what(),用来获取“型别本身以外的附加信息”。除了what(),再没有任何异常提供任何其它成员函数,能够描述异常的种类。因此唯一通用的异常评估手段,大概只有打印了:

try{
  ...
}
catch(const std::exception& error){
    std::cerr<<error>what()<<std::endl;
}

c++中输出通常信息的函数为cout,比如:

std::cout << "Hello world";

cerr通常用于输出错误信息与其他不属于正常逻辑的输出内容。在异常处理机制中则使用cerr来输出错误信息,比如:

std::cerr << "Error: too many arguments\n";

抛出标准异常

允许你在自己的程序中抛出的标准异常有:logic_error及其派生类、runtime_error及其派生类、ios_base::failure。

想要抛出一个标准异常,只需生成一个描述该异常的字符串,并将它初始化,交给异常对象。该字符串将成为被what()返回的描述字符串。

std::string s;
...
throw std::out_of_range(s);

异常安全性(exception safety)

当异常被抛出时,带有异常安全性的函数会:

  • 不泄漏任何资源
  • 不允许数据败坏

异常安全函数提供以下三个保证之一:(对大部分函数而言,抉择往往落在基本保证和强烈保证之间)

  1. 基本承诺:如果异常被抛出,程序内的任何事 物仍然保持在任何一个有效状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态(例如所有的class约束条件都继续获得满足)。

  2. 强烈保证:如果异常被抛出,程序状态不改变。也就是如果函数成功,就是完全成功,如果函数失败,程序会恢复到调用函数之前的状态。

    “copy and swap “策略会导致强烈保证。该策略的原则:为打算修改的对象(原件)做一个副本,在副本身上做一切必要的修改,若有任何修改动作抛出异常,原件仍然保持未改变状态。待所有改变都成功后,再将修改过的副本和原件在一个不抛出异常的操作中置换(swap)。

  3. 不抛掷(nothrow)保证:承诺绝不抛出异常,因为它们总是能够完成原先承诺的功能。作用于内置类型身上的所有操作都提供该保证。

函数的声明式并不能告诉你函数是否是正确的、可移植的或高效的,也不能够告诉你是否提供任何异常安全性保证。所有这些性质都由函数的实现决定,无关乎声明。

函数提供的“异常安全保证”通常最高只等于其所调用之各个函数的“异常安全保证”中的最弱者

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值