用于大型程序的工具

--异常处理[续1]

四、又一次抛出

有可能单个catch不能全然处理一个异常。在进行了一些校正行动之后,catch可能确定该异常必须由函数调用链中更上层的函数来处理,catch能够又一次抛出将异常传递给函数调用链中更上层的函数。又一次抛出是后面不跟类型或表达式的一个throw:

        throw;

空throw语句将又一次抛出异常对象,它仅仅能出如今catch或从catch调用的函数中。假设在处理代码不活动时碰到空throw,就调用terminate函数。

尽管又一次抛出不指定自己的异常,但仍然将一个异常对象沿链向上传递,被抛出的异常是原来的异常对象,而不是catch形參。当catch形參是基类类型的时候,我们不知道由又一次抛出表达式抛出的实际类型,该类型取决于异常对象的动态类型,而不是catch形參的静态类型。比如,来自带基类类型形參catch的又一次抛出,可能实际抛出一个派生类型的对象。

一般而言,catch能够改变它的形參。在改变它的形參之后,假设catch又一次抛出异常,那么仅仅有当异常说明符是引用的时候,才会传播那些改变

    catch (my_error &eObj)
{
eObj.status = severeErr;
throw; //传播改变
}
catch (other_error eObj)
{
e.status = badErr;
throw; //仅仅是复制对象
}

五、捕获全部异常的处理代码

能够使用捕获全部异常catch子句来处理不知道确切类型的异常。捕获全部异常的catch子句形式为(...),比如:

    catch (...)
{
//...
}

捕获全部异常的catch子句与随意类型的异常都匹配。

catch(...)常常与又一次抛出表达式结合使用,catch完毕可做的全部局部工作,然后又一次抛出异常:

void manip()
{
try
{
//...
}
catch (...)
{
//...
throw;
}
}

【注解】

假设catch(...)与其它catch子句结合使用,它必须是最后一个,否则,不论什么跟在它后面的catch子句都将不能被匹配。

六、函数測试块与构造函数

在进入构造函数函数体之前处理构造函数初始化式,构造函数函数体内部的catch子句不能处理在处理构造函数初始化式时可能发生的异常。

为了处理来自构造函数初始化式的异常,必须将构造函数编写为函数try块。能够使用函数測试块将一组catch子句与函数联成一个总体。

template <class T> Handle<T>::Handle(T *p)
try :
ptr(p),use(new size_t(1))
{
//empty function body
}
catch (const std::bad_alloc &e)
{
handle_out_of_memory(e);
}

注意:关键词try出如今成员初始化列表之前,而且測试块的复合语句包围了构造函数的函数体。catch子句既能够处理从成员初始化列表中抛出的异常,也能够处理从构造函数函数体中抛出的异常!

因此:构造函数要处理来自构造函数初始化式的异常,唯一方法是将构造函数编写为函数測试块!

//P587 习题17.5
//(a)
class exceptionType {};
throw new exceptionType();
catch(exceptionType *pet)
{
//...
}

//(b)
throw 8;
catch (...)
{
//...
}

//(c)
enum mathErr {overflow,underflow,zeroDivide};
throw overflow;
catch (mathErr &ref)
{
//...
}

//(d)
typedef int EXCEPTYPE;
throw 250;
catch(EXCEPTYPE)
{
//...
}

七、异常类层次
exception类型所定义的唯一操作是一个名为what的虚成员,该函数返回const char *对象,它一般返回用来在抛出位置构造异常对象的信息。由于what是虚函数,假设捕获了基类类型的引用,对what函数的调用将执行适合异常对象的动态类型的版本号。

1、用于书店应用程序的异常类
应用程序常常通过从exception类或者中间基类派生附加类型来扩充exception层次。这些新派生的类能够表示特定于应用程序领域的异常类型。

标准exception类层次

我们能够定义自己的异常层次来表示可能出现的特定于应用程序的问题。

class out_of_stock : public std::runtime_error
{
public:
explicit out_of_stock(const std::string &s):
std::runtime_error(s) {}
}; class isbn_mismatch : public std::logic_error
{
public:
isbn_mismatch(const std::string &s):std::logic_error(s) {}
isbn_mismatch(const std::string &s,
const std::string &lhs,const std::string &rhs):
std::logic_error(s),
left(lhs),right(rhs) {} const std::string left,right;
virtual ~isbn_mismatch() throw() {}
};

通过从标准异常类派生,定义了特定于应用程序的异常类型,能够觉得异常类按层次组织:随着层次的加深,每一层变得更特殊的异常。

第一层即最一般的层由exception类代表,当捕获这一类型的对象时,我们所知道的仅仅是有些地方出错了

第二层将exception特化为两个大类:执行时错误和逻辑错误。我们的书店异常类表示更特化的层中的事件。out_of_stock类表示可能在执行时出现故障的特定于应用程序的事情,能够用它发出不能履行某个订单的信号。isbn_mismatch异常是从logic_error派生的更特殊的异常,原则上,程序能够通过调用same_isbn检測到不匹配的ISBN。

2、使用程序猿定义的异常类型

用和使用标准库类同样的方法使用自己的异常类

Sales_item operator+(const Sales_item &lhs,const Sales_item &rhs)
{
if (!lhs.same_isbn(rhs))
{
throw isbn_mismatch("isbn mismatch",lhs.book(),rhs.book());
} Sales_item ret(lhs);
ret += rhs;
return ret;
}

然后,使用加操作符的代码能够检測这个错误,写出适当的错误消息:

    Sales_item item1,item2,sum;
while (cin >> item1 >> item2)
{
try
{
sum = item1 + item2;
}
catch (const isbn_mismatch &e)
{
cerr << e.what() << ": left isbn(" << e.left
<< "),right isbn(" << e.right << ")"
<< endl;
}
}

C++ Primer 学习笔记_88_用于大型程序的工具 --异常处理[续1]的更多相关文章

  1. C++ Primer 学习笔记_87_用于大型程序的工具 --异常处理

    用于大型程序的工具 --异常处理 引言: C++语言包括的一些特征在问题比較复杂,非个人所能管理时最为实用.如:异常处理.命名空间和多重继承. 相对于小的程序猿团队所能开发的系统需求而言,大规模编程[ ...

  2. C++ Primer 学习笔记_95_用于大型程序的工具 --多重继承与虚继承

    用于大型程序的工具 --多重继承与虚继承 引言: 大多数应用程序使用单个基类的公用继承,可是,在某些情况下,单继承是不够用的,由于可能无法为问题域建模,或者会对模型带来不必要的复杂性. 在这些情况下, ...

  3. C++ Primer 学习笔记_91_用于大型程序的工具 --命名空间

    用于大型程序的工具 --命名空间 引言: 在一个给定作用域中定义的每一个名字在该作用域中必须是唯一的,对庞大.复杂的应用程序而言,这个要求可能难以满足.这样的应用程序的全局作用域中一般有很多名字定义. ...

  4. 【c++ Prime 学习笔记】第18章 用于大型程序的工具

    大规模应用程序的特殊要求包括: 在独立开发的子系统之间协同处理错误:异常处理 使用各种库(可能包含独立开发的库)进行协同开发:命名空间 对比较复杂的应用概念建模:多重继承 18.1 异常处理 异常处理 ...

  5. 【C++ Primer】用于大型程序的工具

    1. 异常处理 异常以类似于将实參传递给函数的方式抛出和捕获.异常可以是可传给非引用实參的随意实參的类型,这意味着必须可以复制该类型的对象. 当抛出一个表达式的时候,被抛出对象的静态编译时类型将决定异 ...

  6. C++ Primer 5th 第18章 用于大型程序的工具

    C++大规模程序设计至少存在三个特殊要求: 错误处理 库的引入 复杂建模 以上三种对应C++语言的三种特性:异常处理.命名空间.多重继承. 异常处理 异常处理机制是一种允许偷懒的工具,在出现非正确的情 ...

  7. C++ 用于大型程序的工具

    <C++ Primer 4th>读书笔记 相对于小的程序员团队所能开发的系统需求而言,大规模编程对程序设计语言的要求更高.大规模应用程序往往具有下列特殊要求: 1. 更严格的正常运转时间以 ...

  8. C++ Primer 学习笔记_72_面向对象编程 --句柄类与继承[续]

    面向对象编程 --句柄类与继承[续] 三.句柄的使用 使用Sales_item对象能够更easy地编写书店应用程序.代码将不必管理Item_base对象的指针,但仍然能够获得通过Sales_item对 ...

  9. C/C++基础----用于大型程序的工具(异常处理,命名空间,多重继承)

    独立开发的子系统间协同处理错误的能力 使用各种库(可能包含独立开发的库进行协同开发的能力) 对比复杂的应用概念建模的能力 异常处理 异常将问题的检测和解决过程分离开 当执行一个throw之后,程序控制 ...

随机推荐

  1. php composer包管理工具

    一 . 包管理工具 你在Centos上装工具的时候直接yum -y install xx 比你去rpm -ivh xx.rpm 是不是爽很多呢? composer 就是安装php 代码的一个类似工具. ...

  2. mud目录命令说明

      目錄結構 以下列出的是 ES2 mudlib 根目錄下標準的子目錄結構,以及簡短的說明. /adm 儲存由系統管理者所管理的程式與資料檔. /std 儲存標準物件的程式碼. /obj 儲存通用物件 ...

  3. codeforces 27E . Number With The Given Amount Of Divisors 搜索+数论

    题目链接 首先要知道一个性质, 一个数x的因子个数等于 a1^p1 * a2^p2*....an^pn, ai是x质因子, p是质因子的个数. 然后就可以搜了 #include <iostrea ...

  4. MVC3 带查询的分页Helper

    接上篇mvc3 分页Helper. 带查询的分页Helper是在上一篇分页的基础上来的.下面看代码: 首先,在System.Web.Mvc命名空间下的自定义类HtmlPage下面添加一个用于处理“查询 ...

  5. 让两个Div并排显示

    一.使用display的inline属性 <div style="width:300px; height:auto; float:left; display:inline"& ...

  6. 深入Android媒体存储服务(二):磁盘扫描流程

    简介: 本文是<深入Android媒体存储服务>系列第二篇,简要介绍媒体存储服务扫描文件的流程.文中介绍的是 Android 4.2. Android 有一套媒体存储服务,进程名是 and ...

  7. android一分钟学会可视化操作数据库(无需ROOT)

    我刚开始弄android数据库的时候,想查询一些数据,以验证程序逻辑,发现很多方案都需要ROOT. 即便有不需要ROOT的方案,命令行交互也比较麻烦. 今天跟大家分享一下这个点点鼠标就能实现的功能. ...

  8. Delphi中TFlowPanel实现滚动条效果

    由于TFlowPanel中没有设置滚动条的相关属性.所以我们只好另辟溪径.再加一个tscrollbox来实现. 具体操作如下: 1,先添加一个Tscrollbox,设置其align为alclient. ...

  9. poj 3273 Monthly Expense (二分搜索,最小化最大值)

    题目:http://poj.org/problem?id=3273 思路:通过定义一个函数bool can(int mid):=划分后最大段和小于等于mid(即划分后所有段和都小于等于mid) 这样我 ...

  10. bootstrap栅格系统的div高度怎样定?

    不能直接写px,不同设置分辨不同,div宽度始终是满屏的,如果高度指定像素大小,div就不能保证长宽比例恰当了. 解决方法: height:0px;padding-bottom:100%