C++大规模程序设计至少存在三个特殊要求:

  • 错误处理
  • 库的引入
  • 复杂建模

以上三种对应C++语言的三种特性:异常处理、命名空间、多重继承。

异常处理

异常处理机制是一种允许偷懒的工具,在出现非正确的情况时,进行错误之间的协作处理。异常使得问题检测和解决过程分离开来。程序的一部分检测问题,另一个部分专门解决问题。

抛出异常

在C++中通过抛出一个表达式来引发异常,被抛出的表达式的类型以及当前调用链共同决定哪个部分来处理异常。被选择的部分是调用链和抛出类型匹配最近的处理部分。根据抛出类型的类型及其内容,处理部分能够得知到底发生了什么错误。

当使用throw进行异常抛出时,throw语句后的下一条代码语句不再被执行,程序的执行控制权跳转到匹配的异常处理catch模块。该catch模块可能和异常抛出部分同属一个函数体,也可能是直接或间接调用链上的函数中。这会导致两个结果:

  • 沿着调用链的函数可能会提早退出
  • 一旦开始进行异常处理,调用链上创建的对象会被销毁(对类类型对象来说,会执行析构函数)

举个例子来说:A函数调用了B函数,B函数又调用了C函数,这形成了一个栈式的调用链A->B->C,C函数中途错误并抛出了一个异常,C函数没有异常处理部分,因此逆序回溯调用链回到B,而B也没有异常处理部分,继续逆序回溯调用链回到A,A中含有异常处理部分,因此异常在A中被处理消化,这其中B和C都没有正常结束,它们都提早退出了。另外,由于最终异常在A中处理,那么B和C执行到一半时之前已经创建的那些对象都会被销毁。throw的作用类似于return。

栈展开

当程序抛出一个异常之后,程序暂停当前函数执行,并立即开始沿着调用链查找catch处理部分。当throw出现在一个try语句块中时,编译器检查与该try配对的catch语句,如果找到且匹配,那么就使用该catch处理。如果没找到,则在外层作用域中查找匹配的。如果找遍当前函数都无法找到,那么退出该函数,逆序回溯调用链继续前面的方法继续查找,最终要么找到调用匹配的进行处理,要么没有找到调用terminate终止程序。上述这个查找的过程被称为栈展开。当找到匹配的catch处理之后,程序将在匹配的catch处理模块之后的非catch模块开始执行。

在栈展开的过程中,调用链上创建的局部对象会被销毁。对类类型对象来说,会执行析构函数,因此通常来说,析构函数不允许再抛出异常,应该在析构函数内部把异常消化掉。

异常对象

异常对象是一种特殊的对象,编译器使用异常抛出表达式来对异常对象进行拷贝初始化,如果该表达式是一个类类型,则该类析构函数和拷贝或移动构造函数必须正常,如果表达式是一个数组或函数类型,则表达式会退化成相应的指针类型。

异常对象在使用完毕后会被销毁,另外,在栈展开过程中,调用链上的函数可能会提早退出,所以不允许抛出一个指向局部变量的指针。

捕获异常

catch子句的语法同函数类似,拥有一个形参列表和函数体,但没有返回值。同函数的形参类似,catch的形参列表也可以没有形参名,而只有一个形参类型,或者形参是一个左值引用(不允许是右值引用)。

异常的处理catch语句的搜索过程,并不会根据最佳匹配来挑选,而是根据顺序,因此约束专门的catch语句越应该排在前面,尤其是在继承体系中,派生类应该在基类前。

异常对象匹配时,是不允许类型转换的,只允许const可以绑定到非const上,数组退化指针,派生类转换为基类,除此之外,任何类型转换都不允许,即使是double向int这样的内置类型间的转换。

重新抛出

有时,一个catch子句并不能把所有问题处理妥当,此时允许该catch重新抛出,通过重新抛出将异常传递给另外的catch子句,重新抛出的语法是使用一个throw语句,不含任何表达式:

throw;

该throw语句只能出现在catch子句之内或者嵌套在catch子句更深的内部,否则编译器会调用terminate。重新抛出的对象如果是以引用方式获得的,那么catch中的更改才能得以保留。

捕获任意类型的异常

有时候,我们对所有的异常处理都是使用同一种方法而不论异常的类型是什么,这时可以通过特殊的语法捕获所有异常,方法如下:

catch( ... )
{
...
}

通过使用省略符号( ... )来作为catch子句的参数,这样能匹配所有的异常,如前面提及的:catch子句不是根据最佳类型匹配,而是根据顺序匹配。因此,通用的错误匹配捕获语句一般防止catch列表的最后。

C++ Primer 5th 第18章 用于大型程序的工具的更多相关文章

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

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

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

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

  3. C++ Primer 学习笔记_88_用于大型程序的工具 --异常处理[续1]

    用于大型程序的工具 --异常处理[续1] 四.又一次抛出 有可能单个catch不能全然处理一个异常.在进行了一些校正行动之后,catch可能确定该异常必须由函数调用链中更上层的函数来处理,catch能 ...

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

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

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

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

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

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

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

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

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

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

  9. C++ Primer 5th 第1章 开始

    *****代码在Ubuntu g++ 5.31 / clang++ 3.8(C++11)下编写调试***** 每个C++程序必须有一个main( )函数,main( )函数的返回值也必须是int类型, ...

随机推荐

  1. object & over-write

    object & over-write

  2. window.location.hash 使用

    [转]http://www.cnblogs.com/nifengs/p/5104763.html location是javascript里边管理地址栏的内置对象,比如location.href就管理页 ...

  3. BZOJ5102 POI2018Prawnicy(堆)

    考虑固定右端点,使左端点最小.那么按右端点排序后查询前缀这些区间的左端点第k小即可.然而写了一个treap一个线段树都T飞了,感觉惨爆.事实上可以用堆求第k小,维护一个大根堆保证堆中元素不超过k个即可 ...

  4. 【uoj122】 NOI2013—树的计数

    http://uoj.ac/problem/122 (题目链接) 题意 给出一棵树的dfs序和bfs序,保证一定可以构成一棵树.问构成的树的期望深度. Solution 这是一个悲伤的故事,我YY的东 ...

  5. phpredis -- Redis Arrays用法

    Redis Arrays 来自地址:https://github.com/phpredis/phpredis/blob/master/arrays.markdown#readme 扩展原文件array ...

  6. 多项式 Wannafly挑战赛22

    后缀表达式 大整数(加法.乘法.gcd java) import java.math.BigInteger; import java.util.Scanner; class Work { String ...

  7. 论C语言中二级指针和二维数组之间的区别

    刚开始学习C语言的时候,觉得一个数组可以定义一个一级指针去访问,想当然的就觉得可以定义一个二级指针去访问二维数组.很显然这是错误的. 我们来看看C语言的数组在内存中的存储方式. 实际上C语言中的数组, ...

  8. Java入门:练习——自定义通用工具类

    请编写一个通用工具类,该类具有如下功能: 1)判断一个字符串是否是邮箱地址 2)判断一个字符串是否是手机号码 3)判断一个字符串是否是电话号码 4)判断一个字符串是否是IP地址 代码结构如下,请补充完 ...

  9. 关于JSON的解析方式

    借鉴:站在巨人的肩膀上 一.json-lib json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,在Json.org网站上,Java可以使用 ...

  10. 数据分析与展示---Pandas库入门

    简介 一:Pandas库的介绍 二:Pandas库的Series类型 (一)索引 (1)自动索引 (2)自定义索引 (二)Series类型创建 (1)列表创建 (2)标量值创建 (3)字典类型创建(将 ...