C++ Primer 5th 第18章 用于大型程序的工具
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章 用于大型程序的工具的更多相关文章
- 【c++ Prime 学习笔记】第18章 用于大型程序的工具
大规模应用程序的特殊要求包括: 在独立开发的子系统之间协同处理错误:异常处理 使用各种库(可能包含独立开发的库)进行协同开发:命名空间 对比较复杂的应用概念建模:多重继承 18.1 异常处理 异常处理 ...
- C++ Primer 学习笔记_95_用于大型程序的工具 --多重继承与虚继承
用于大型程序的工具 --多重继承与虚继承 引言: 大多数应用程序使用单个基类的公用继承,可是,在某些情况下,单继承是不够用的,由于可能无法为问题域建模,或者会对模型带来不必要的复杂性. 在这些情况下, ...
- C++ Primer 学习笔记_88_用于大型程序的工具 --异常处理[续1]
用于大型程序的工具 --异常处理[续1] 四.又一次抛出 有可能单个catch不能全然处理一个异常.在进行了一些校正行动之后,catch可能确定该异常必须由函数调用链中更上层的函数来处理,catch能 ...
- C++ Primer 学习笔记_87_用于大型程序的工具 --异常处理
用于大型程序的工具 --异常处理 引言: C++语言包括的一些特征在问题比較复杂,非个人所能管理时最为实用.如:异常处理.命名空间和多重继承. 相对于小的程序猿团队所能开发的系统需求而言,大规模编程[ ...
- C++ Primer 学习笔记_91_用于大型程序的工具 --命名空间
用于大型程序的工具 --命名空间 引言: 在一个给定作用域中定义的每一个名字在该作用域中必须是唯一的,对庞大.复杂的应用程序而言,这个要求可能难以满足.这样的应用程序的全局作用域中一般有很多名字定义. ...
- 【C++ Primer】用于大型程序的工具
1. 异常处理 异常以类似于将实參传递给函数的方式抛出和捕获.异常可以是可传给非引用实參的随意实參的类型,这意味着必须可以复制该类型的对象. 当抛出一个表达式的时候,被抛出对象的静态编译时类型将决定异 ...
- C++ 用于大型程序的工具
<C++ Primer 4th>读书笔记 相对于小的程序员团队所能开发的系统需求而言,大规模编程对程序设计语言的要求更高.大规模应用程序往往具有下列特殊要求: 1. 更严格的正常运转时间以 ...
- C/C++基础----用于大型程序的工具(异常处理,命名空间,多重继承)
独立开发的子系统间协同处理错误的能力 使用各种库(可能包含独立开发的库进行协同开发的能力) 对比复杂的应用概念建模的能力 异常处理 异常将问题的检测和解决过程分离开 当执行一个throw之后,程序控制 ...
- C++ Primer 5th 第1章 开始
*****代码在Ubuntu g++ 5.31 / clang++ 3.8(C++11)下编写调试***** 每个C++程序必须有一个main( )函数,main( )函数的返回值也必须是int类型, ...
随机推荐
- ACM数论之旅4---扩展欧几里德算法(欧几里德(・∀・)?是谁?)
为什么老是碰上 扩展欧几里德算法 ( •̀∀•́ )最讨厌数论了 看来是时候学一学了 度娘百科说: 首先, ax+by = gcd(a, b) 这个公式肯定有解 (( •̀∀•́ )她说根据数论中的相 ...
- RTMP、RTSP、HTTP视频协议详解(附:直播流地址、播放软件)
- Linux禁止root账户远程登录
Linux系统中,root用户几乎拥有所有的权限,远高于Windows系统中的administrator用户权限.一旦root用户信息被泄露,对于我们的服务器来说将是极为致命的威胁.所以禁止root用 ...
- Common Substrings POJ - 3415(长度不小于k的公共子串的个数)
题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1 sa[i] < len1 和 sa[i-1] < ...
- BZOJ4727 [POI2017]Turysta 【竞赛图哈密顿路径/回路】
题目链接 BZOJ4727 题解 前置芝士 1.竞赛图存在哈密顿路径 2.竞赛图存在哈密顿回路,当且仅当它是强联通的 所以我们将图缩点后,拓扑排序后一定是一条链,且之前的块内的点和之后块内的点的边一定 ...
- 手机数据抓包的N种方法
手机数据抓包的N种方法 - xia_xia的博客 - 博客频道 - CSDN.NEThttp://blog.csdn.net/xia_xia0919/article/details/50606137 ...
- 简例 - robot case格式
注意robot的case格式 # *** Variables *** # *** Settings *** # Library String # Library Selenium2Library ** ...
- Long与long的区别
Java的数据类型分两种:1.基本类型:long,int,byte,float,double,char2. 对象类型(类): Long,Integer,Byte,Float,Double,Char,S ...
- 题解【CF103D Time to Raid Cowavans】
Description 给一个序列 \(a\) ,\(m\) 次询问,每次询问给出 \(t, k\) .求 \(a_t + a_{t+k}+a_{t+2k}+\cdots+a_{t+pk}\) 其中 ...
- JVM加载一个类的过程
类的加载过程 Java源代码被编译成class字节码,JVM把描述类数据的字节码.Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机 ...