基础知识

异常处理机制有两个主要成分:异常的鉴定和发出,以及异常的处理方式。通常,不论是membe function和non-member function,都有可能产生异常以及处理异常。异常出现后,正常程序的执行便被暂停(suspended)。与此同时,异常处理机制开始搜索程序中有能力处理这一异常的地点。异常被处理完毕之后,程序的执行便会继续(resume),从异常处理点接着执行下去。

所谓异常(exception)是某种对象,最简单的异常对象可以设计为整数或字符串。大部分时候,被抛出的异常都属于特定的异常类(也许形成一个继承体系)。

我们可以利用单条或一连串的catch字句来捕获(catch)被抛出的异常对象。catch子句有三部分组成:关键字catch、小括号内的一个类型或对象、大括号内的一组语句(用以处理异常)。抛出的异常对象类型会被拿来逐一地和每个catch子句比对。如果类型符合,那么该catch子句的内容便会被执行,在通过所有catch子句之后,由正常程序重新接手。有时我们可能无法完成异常的完整处理过程,在记录信息之外,我们或许需要重新抛出(rethrow)异常,以寻求其它catch子句的协助,做进一步的处理,重新抛出时,只需写下关键字throw即可,它只能出现于catch子句中,它会将捕获的异常对象再一次抛出,并由另一个类型符合的catch子句接手处理。如果我们想要捕获任何类型的异常,可以使用一网打尽(catch-all)的方式,只需在异常声明部分指定省略号(…)即可。

catch子句应该和try块相应而生。try块是以关键字try作为开始,然后是大括号内的一连串程序语句。catch子句放在try块的末尾,这表示如果try块内有任何异常发生,便由接下来的catch子句加以处理。

当函数的try块发生某个异常,但并没有相应的catch子句将它捕获,此函数便会被中断,由异常处理机制接管,沿着“函数调用链”一路回溯,搜寻符合条件的catch子句。如果“函数调用链”不断被解开,一直回到main()还是找不到合适的catch子句,变调用标准库提供的terminate()——其默认行为是中断整个程序的执行。

练习题答案

练习7.3 为练习5.2的Stack类体系加入两个异常类型,处理“想从空stack中取出元素”和“想为满stack添加元素”两种错误。请显示修改后的pop()和push()。

定义PopOnEmpty和PushOnFull两个异常类,分别供pop()和push()抛出。于是,Stack的所有member function就不再需要返回代表成功或失败的值了:

void pop(elemType& elem)
{
if (empty())
throw PopOnEmpty;
elem = _stack[--_top];
_stack.pop_back();
} void push(const elemType& elem)
{
if (!full())
{
_stack.push_back(elem);
++_top;
return;
}
throw PushOnFull();
}

为了让这两个Stack异常可以被完全不知情的其它组件捕获,它们应该融入StackException继承体系中,后者又应该派生自标准库所提供的logic_error class。

logic_error派生自exception。exception是标准库的所有异常类别继承体系的最根本抽象基类。这个继承体系有一个名为what()的虚函数,会返回const char*,用以表示被捕获的异常究竟为何。

class StackException :public logic_error
{
public:
StackException(const char* what) :_what(what) {}
const char* what() const { return _what.c_str(); } protected:
string _what;
}; class PopOnEmpty :public StackException
{
public:
PopOnEmpty() :StackException("Pop on Empty Stack") {}
}; class PushOnFull :public StackException
{
public:
PushOnFull() :StackException("Push on Full Stack") {}
};

以下任何一个catch子句都能够处理类型为PushOnFull的异常:

catch (const PushOnFull & pof)
{
log(pof.what());
return;
}
catch (const StackException & stke)
{
log(stke.what());
return;
}
catch (const logic_error & lge)
{
log(lge.what());
return;
}
catch (const PushOnFull & ex)
{
log(ex.what());
return;
}

end。

“A programmer who subconsciously views himself as an artist will enjoy what he does and will do it better.”

#《Essential C++》读书笔记# 第七章 异常处理的更多相关文章

  1. Getting Started With Hazelcast 读书笔记(第七章)

    第七章 部署策略 Hazelcast具有适应性,能根据不同的架构和应用进行特定的部署配置,每个应用可以根据具体情况选择最优的配置: 数据与应用紧密结合的模式(重点,of就是这种) 胖客户端模式(最好用 ...

  2. 《R语言实战》读书笔记 第七章--基本统计分析

    在导入数据并且将数据进行组织和初步可视化以后,需要对数据进行分布探索和两两关系分析等.主要内容有描述性统计分析.频数表和列联表.相关系数和协方差.t检验.非参数统计. 7.1描述性统计分析 7.1.1 ...

  3. 深度探索C++对象模型读书笔记-第七章站在对象模型的尖端

    Template 模板是在编译时期而非执行时期被计算的.因此其不会带来效率的降低. 1: const Point<float> &ref = 0; 该语句会实例化一个Point的f ...

  4. 《利用python进行数据分析》读书笔记--第七章 数据规整化:清理、转换、合并、重塑(三)

    http://www.cnblogs.com/batteryhp/p/5046433.html 5.示例:usda食品数据库 下面是一个具体的例子,书中最重要的就是例子. #-*- encoding: ...

  5. 《C#从现象到本质》读书笔记(七)第9章 泛型

    <C#从现象到本质>读书笔记(七)第9章 泛型 泛型的三大好处:类型安全,增强性能(避免装箱和拆箱),代码复用. 泛型方法是传入的参数至少有一个类型为T(尚未制定的类型,根据微软的命名规则 ...

  6. 《Linux内核设计与实现》读书笔记——第五章

    <Linux内核设计与实现>读书笔记--第五章 标签(空格分隔): 20135321余佳源 第五章 系统调用 操作系统中,内核提供了用户进程与内核进行交互的一组接口.这些接口让应用程序受限 ...

  7. Essential C#读书笔记

    Essential C#读书笔记 这是一个多变的时代,一次又一次的浪潮将不同的人推上了巅峰.新的人想搭上这一波,同时老的人也不想死在沙滩上.这些年新的浪潮又一次推开,历史不停地重复上演,那便是移动互联 ...

  8. Android群英传笔记——第七章:Android动画机制和使用技巧

    Android群英传笔记--第七章:Android动画机制和使用技巧 想来,最 近忙的不可开交,都把看书给冷落了,还有好几本没有看完呢,速度得加快了 今天看了第七章,Android动画效果一直是人家中 ...

  9. 《Linux内核设计与实现》第八周读书笔记——第四章 进程调度

    <Linux内核设计与实现>第八周读书笔记——第四章 进程调度 第4章 进程调度35 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配 ...

随机推荐

  1. 解决虚拟机中Linux不能上网的问题

    第一步.虚拟机中的设置 点击右上角的网络标识,点击network settings,选择Wired,Add Profile,IPv4,Addresses设置成Automatic(DHCP),完成设置点 ...

  2. Docker基础内容之容器

    前言 容器是独立运行的一个或一组应用以及它们的运行态环境. 相关命令 启动容器相关命令 docker run 运行一个ubuntu14.04版本的容器,如果这个镜像本地不存在则会去默认仓库中下载 do ...

  3. Linux文件内容重定向

    文件描述符 可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作. 用户可以自定义文件描述符范围是:3-num,这个最大数字, ...

  4. Oracle数据库、实例、用户、表空间、表之间的关系

    完整的Oracle数据库通常由两部分组成:Oracle数据库和数据库实例. 1) 数据库是一系列物理文件的集合(数据文件,控制文件,联机日志,参数文件等): 2) Oracle数据库实例则是一组Ora ...

  5. 前端 JS/TS 调用 ASP.NET Core gRPC-Web

    前言 在上两篇文章中,介绍了ASP.NET Core 中的 gRPC-Web 实现 和 在 Blazor WebAssembly 中使用 gRPC-Web,实现了 Blazor WebAssembly ...

  6. Ubuntu解决 MariaDB无密码就可以登录的问题

    使用apt-get来安装mysql,安装好之后发现安装的是 MariaDB,如下,无需密码既可以登录了.即使使用mysqladmin或mysql_secure_installation 设置好密码,用 ...

  7. shell正则表达式提取数字

    grep 提取数字 grep -Po "\d+\.\d+"

  8. A Hybrid Data Association Framework for Robust Online Multi-Object Tracking(2017 IEEE Transactions on Image Processing)

    A Hybrid Data Association Framework for Robust Online Multi-Object Tracking 一种用于鲁棒在线多目标跟踪的混合数据关联框架 摘 ...

  9. ELK:收集Docker容器日志

    简介 之前写过一篇博客 ELK:日志收集分析平台,介绍了在Centos7系统上部署配置使用ELK的方法,随着容器化时代的到来,容器化部署成为一种很方便的部署方式,收集容器日志也成为刚需.本篇文档从 容 ...

  10. 第2章 Java并行程序基础(二)

    2.3 volatile 与 Java 内存模型(JMM) volatile对于保证操作的原子性是由非常大的帮助的(可见性).但是需要注意的是,volatile并不能代替锁,它也无法保证一些复合操作的 ...