内容概览

一图解百问,但是有些地方我们需要特别指出:

  1. 类型在这里指通过typedef重定义的,例如函数类型、指针类型等。
  2. exception_ptr 在标准中是未定义具体实现的,因此它可能是类也可能是类型
  3. uncaught_exception()uncaught_exceptions() 是两个不同的函数,分别 判断是否有未处理异常返回未处理异常的个数 。 其中,uncaught_exceptions()函数仅在C++14开始出现。

仔细观察上图,你就能发现标准库给我们提供了以下几个方面的异常处理支持:

  • 未捕获异常处理
  • 异常嵌套
  • 异常重抛

未捕获异常处理

其实未捕获异常可以分为两类,一类有关try-catch块,另一类有关dynamic-exception-specification(动态异常指定)。

try-catch

当抛出的异常未被catch块捕获时,标准库的terminate()函数会被自动调用,默认情况下该函数调用abort()函数非正常终止程序。 非正常终止是什么意思呢? 这里我们引用标准的一句话来解释:

The program is terminated without destroying any object and without calling any of the functions passed to atexit or at_quick_exit.

大概意思是说,非正常终止不会析构任何对象,也不会调用任何通过atexit 或者 at_quick_exit注册的处理函数

很明白的,程序的资源释放会成为一个严重的问题。 因此,标准库提供了set_terminate()get_terminate()来帮助用户获取和设置处理器做一些必要的清理工作 、让用户来决定是否终止程序

dynamic-exception-specification(C++11中已废弃)

在C++11之前,函数签名中还可以指定抛出的异常类型(如果有):

void function() throw(int)	{...}

如上,如果该function函数抛出了任何非int异常类型,unexpected()函数也会被自动调用。 为此,C++标准甚至特地规定了一个bad_exception异常类来表示这种情况。 我们把这类情况也称为未捕获,该函数默认调用terminate()函数,不再赘述。

但是,但是,该特性在实践中被证明非常“鸡肋”, 因此从C++11开始被标记为废弃。

异常嵌套

为了支持异常嵌套,标准库提供了三个积木: nested_exception异常类 、throw_with_nested函数 、rethrow_if_nested函数。

如何嵌套

标准定义了一个异常类nested_exception,这个类非常特殊,它没有继承自通用的异常基类exception。 标准指出,该类是为了继承之用,以配合其它两个函数实现嵌套异常机制

如何构造嵌套

答:使用函数构造并抛出,以下是模版函数原型:

template <class T> [[noreturn]] void throw_with_nested(T&& t);

该函数将当前异常类(正在处理的异常类)与传入类型构造成一个嵌套类型, 当前异常类为nested-exception,传入类型为outer-exception。

如何解嵌套

答: 使用函数解嵌套并重抛,以下是函数原型:

template <class E> void rethrow_if_nested(const E& e);

如果传入异常类型为嵌套异常,该函数会抛出被嵌套的异常。

个人感觉

看样子,C++标准是打算提供一个方便的异常嵌套模型供开发者使用,但是给我的感觉确非常别扭。 从嵌套构造上来讲,嵌套异常的构造方式非常模糊,需要结合当前上下文,传入一个outer-exception类型也很不舒服;从解嵌套的方法上来讲,抛出似乎是比较合理的获得方式,但该函数名(rethrow_if_nested)不够友好----抛出?是抛出该嵌套异常呢还是被嵌套异常?

异常重抛

重抛的支持非常简单,调用函数:

void rethrow_exception(exception_ptr p);

但是注意,传参是exception_ptr类型,你想要重抛异常的话还需要经过一次类型转换(通过make_exception_ptr()函数)。 -……-怪不得C++总被人诟病别扭。。。

C++ 头文件系列(exception)的更多相关文章

  1. C++ 头文件系列(ios)

    1 简介 我们都知道,平时常用的那些标准流,诸如iostream.ofstream.ifstream等等,其实都是对应的basic_XXX模版的实例类. 而这些basic_XXX类模版又都是继承自同一 ...

  2. C++ 头文件系列(istream)

    1. 简介 其实叫它istream有点不合适,因为该头文件不仅定义了istream,还定义了iostream. 2. basic_istream模版 basic_istream继承自basic_ios ...

  3. C++ 头文件系列(array)

    注意,该头文件仅在C++11中标准才开始出现. 简介 与语言内置的数组一样, array类模版支持几乎所有内置数组包含的特性: 顺序的(sequence) 内存连续的(contiguous stora ...

  4. C++ 头文件系列(queue)

    简介 这个头文件定义了两个跟队列有关的类----quque.priority_queue,分别实现的是队列 和 优先队列这两个概念. 但是与这两个类模版与其它类模版(vector.array等)最大的 ...

  5. C++ 头文件系列(stack)

    简介 该头文件只含有一个类模版stack, 它实现栈的概念,是一个容器适配器(说实话,在写这篇随笔之前我都不知道有这么个类模版). 栈 栈只有一个重要的特性: LIFO(last-in first-o ...

  6. C++ 头文件系列(vector)

    简介 vector头文件包含vector的类模版以及该模版的显示特化版本vector< bool >. vector是C++容器库中非常通用的一种容器,如果你不知道该决定使用哪一种容器,或 ...

  7. C++ 头文件系列(map)

    简介 该头文件包含两个概念相似的容器----map.multimap. 而这两个容器反映的概念就是 映射. 这两个容器 相同 的属性有: 关联性 映射 动态增长 键(Key)唯一性 这两个不相同的属性 ...

  8. C++ 头文件系列(unordered_map、unordered_set)

    简介 很明显,这两个头文件分别是map.set头文件对应的unordered版本. 所以它们有一个重要的性质就是: 乱序 如何乱序 这个unorder暗示着,这两个头文件中类的底层实现----Hash ...

  9. C++ 头文件系列(iterator)

    简介 该头文件围绕迭代器展开,定义了一系列与迭代器有关的概念,但最最最重要的一点就是----它和其它容器一起实现了C++容器的Iterator设计模式. Iterators are a general ...

随机推荐

  1. AngularJS自定义指令之可选参数replace

    replace是一个可选参数,如果设置了这个参数,值必须为true,因为默认值为false.默认值意味着模板会被当作子元素插入到调用此指令的元素内部: 如: <my-directive>& ...

  2. &与&& C语言

    &是一个位运算符,就是将两个二进制的数逐位相与,就是都是1才是1,只要有一个为0则为0,结果是相与之后的结果.&&是一个逻辑运算符,就是判断两个表达式的真假性,只有两个表达式同 ...

  3. 关于ReentrantLock和Condition的用法

    这篇博客是过年后的第一篇博客,2.13正式上班,之前在家休年假.上班第一天公司说有个紧急的项目需要上线,所以我们连续加了两个星期的班,直到上个周六还在加班,终于成功上线了.今天是2月的最后的一天,继续 ...

  4. 整理 - .Net系统预定义的委托们

    大部分情况下,我们可以使用系统预定义的委托类型,而不需要自己再来手动定义. 以下委托都位于System命名空间下. 传入参数.返回值的类型,大都被声明为泛型. 1.Action系列 有0-16个参数, ...

  5. CSS中@import与link的具体区别

    我们知道在网页中引用外部CSS有两种方式:@import和link 我们也经常听到有人说要使用link来引入CSS更好,但是你知道为什么吗? 继续往下看 link:link就是把外部CSS与网页连接起 ...

  6. 如何垂直居中<img>?

    方法1: 父元素设置height=line-height,子元素设置vertical-align:middle; 方法2: 父元素display:table-cell;vertical-align:m ...

  7. Linux 安装DenyHost防止ssh被暴力破解

    DenyHosts介绍 当你的linux服务器暴露在外网当中时,服务器就极有可能会遭到互联网上的扫描软件进行扫描,然后试图连接ssh端口进行暴力破解(穷举扫描).如果遇到这个问题,一款非常有用的工具D ...

  8. if(){}else 语句的正确写法以及它的嵌套使用

    if(一个返回bool值的条件表达式) { 程序块 } else{} 它的执行过程我们可以通过一个程序来了解 static void Main(string[] args) { ) // 条件1 { ...

  9. Spring IOC以及三种注入方式

    IOC是spring的最基础部分,也是核心模块,Spring的其他组件模块和应用开发都是以它为基础的.IOC把spring的面向接口编程和松耦合的思想体现的淋漓尽致. IOC概念 IOC(Invers ...

  10. 腾讯云数据库团队:MySQL数据库的高可用性分析

    作者介绍:易固武,腾讯高级工程师,参与腾讯账号安全建设,腾讯数据仓库(TDW)优化改造,腾讯云数据库等项目,对大规模分布式存储和计算系统有浓厚的兴趣和经历 MySQL数据库是目前开源应用最大的关系型数 ...