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语句,不含任何表达式:

  1. throw;

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

捕获任意类型的异常

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

  1. catch( ... )
  2. {
  3. ...
  4. }

通过使用省略符号( ... )来作为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. POJ3041_Asteroids

    这个题目说,有一个N*N的规格的方格.某些格子里有*号,每次可以消除一行或者一列中所有的*号.最少需要消多少次? 新学到的,什么什么定理,最少点覆盖等于最大匹配数. 这个定理可以这样来理解(看别人的) ...

  2. widows终端远程连接Linux服务器

    一.前言 为什么不是远程连接Linux服务器? 因为我不会,远程连接window我就用电脑自带的“远程桌面连接”. 以下所述都是在CentOS操作系统下的. 服务器刚换成Linux的时候很迷茫,感觉无 ...

  3. Executors提供的四种线程池和自定义线程池

    JAVA并发编程——EXECUTORS 线程池的思想是一种对象池的思想,开放一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完毕,对象 ...

  4. 【刷题】BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊

    Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置 ...

  5. 【2018ICPC青岛】

    B 题意:给n个问题,每个问题有一个固定的答案ai(<=10^5).现在有m个约束关系,每个约束关系是一个二元组(ui,vi),表示你回答ui.vi问题的答案必须一样. 现在让你输出分别修复一个 ...

  6. php的数组转为对象

    有时候数组要转为对象操作,用对象的指向操作符,有两种方法 方法一: $arr=['a'=>10,'b'=>100,'c'=>'Hello']; $obj=(Object)$arr; ...

  7. JUnit中按照顺序执行测试方式

    很多情况下,写了一堆的test case,希望某一些test case必须在某个test case之后执行.比如,测试某一个Dao代码,希望添加的case在最前面,然后是修改或者查询,最后才是删除,以 ...

  8. Linux内核分析实验八------理解进程调度时机跟踪分析进程调度与

    一.进程调度与进程调度的时机分析 1.不同类型的进程有不同的调度需求 Linux既支持普通的分时进程,也支持实时进程. Linux中的调度是多种调度策略和调度算法的混合. 2.调度策略:是一组规则,它 ...

  9. 响应式开发(四)-----Bootstrap CSS----------Bootstrap CSS概览和相关注意事项

    本章先记录一些与Bootstrap CSS相关的一些特点和注意事项以及兼容性. HTML 5 文档类型(Doctype) Bootstrap 使用了一些 HTML5 元素和 CSS 属性.为了让这些正 ...

  10. (转)解决dubbox-demo-provider.xml报错的问题:提示Failed to read schema document

    背景:在eclipse项目中,经常会遇到xml文件提示找不到.xsd文件的情况.很有必要弄清xsd文件的加载过程! 1 解决过程 dubbo-demo-provider导入eclipse后dubbox ...