【C++】《C++ Primer 》第十八章
第十八章 用于大型程序的工具
大规模应用程序的特殊要求包括:
- 在独立开发的子系统之间协同处理错误的能力。
- 使用各种库进行协同开发的能力。
- 对比较复杂的应用概念建模的能力。
一、异常处理
异常处理(exception handling) 机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并作出相应的处理。
1. 抛出异常
- 一个异常如果没有被捕获,则它将终止当前的程序。
- 在栈展开的过程中,运行类类型的局部对象的析构函数。因为这些析构函数是自动执行的,所以它们不应该抛出异常。一旦在栈展开的过程中析构函数抛出了异常,并且析构函数自身没能捕获到该异常,则程序将被终止。
- 当抛出一条表达式时,该表达式的静态编译时类型决定了异常对象的类型。抛出指针要求在任何对应的处理代码存在的地方,指针所指的对象都必须存在。
2. 捕获异常
- 通常情况下,如果
catch接受的异常与某个继承体系有关,则最好将该catch的阐述定义为引用类型。 - 如果在多个
catch语句的类型之间存在着继承关系,则我们应该把继承链最低端的类放在前面,而将继承链最顶端的类放在后面。 - 如果
catch(...)与其他几个catch语句一起出现,则catch(...)必须在最后的位置。出现在捕获所有异常语句后面的catch语句将永远不会被匹配。
3. 函数try语句块与构造函数
- 处理构造函数初始值异常的唯一方法是将构造函数写成函数try语句块。
4. noexcept异常说明
- C++11新标准中,通过提供
noexcept说明符指定某个函数不会抛出异常。
void recoup(int) noexcept; // 不会抛出异常
void alloc(int); // 可能抛出异常
- 可以在函数指针的声明和定义中指定
noexcept;在typedef或类型别名中则不能出现noexcept;在成员函数中,noexcept说明符需要跟在const及其引用限定符之后,final、override或虚函数的=0之前。 noexcept可以用在两种情况下:确定函数不会抛出异常;根本不知道该如何处理异常;- 通常情况下,编译器不能也不必在编译时验证异常说明。
noexcept有两层含义:当跟在函数参数列表后面时它是异常说明符;而当作为noexcept异常说明的bool实参出现时,它是一个运算符。
5. 异常类层次
- 标准exception层次:

- 书店应用程序的异常类
class out_of_staock: 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:
explicit 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;
};
// 使用自定义异常类
Sales_data &Sales_data::operator += (const Sales_data& rhs) {
if(isbn() != rhs.isbn())
throw isbn_mismatch("wrong isbn", isbn(), rhs.isbn());
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
Sales_data 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;
}
}
二、命名空间
多个库将名字放置在全局命名空间中将引发命名空间污染。命名空间(namespace) 为防止名字冲突提供了更加可控的机制。
1. 命名空间定义
- 一个命名空间的定义包括两个部分:首先是关键字namespace,随后是命名空间的名字。在命名空间名字后面是一系列由花括号括起来的声明和定义。只要能出现在全局作用域中的声明就能置于命名空间内,主要包括:类、变量(及其初始化操作)、函数(及其定义)、模板和其他命名空间。
namespace cplusplus_primer {
class Sales_data {};
Sales_data operator+(const Sales_data&, const Sales_data&);
class Query {};
class Query_base {};
}
// 使用
cplusplus_primer::Query q = cplusplus_primer::Query("hello");
- 定义多个类型不相关的命名空间应该使用单独的文件分别表示每个类型(或关联类型构造的集合)。
- 未命名的命名空间是指关键字namespace后紧跟花括号括起来的一系列声明语句。它定义的变量拥有静态生命周期;他们在第一次使用前创建,并且直到程序结束时才销毁。和其他命名空间不同,未命名的命名空间仅在特定的文件内部有效,其作用范围不会横跨多个不同的文件。
int i; // i的全局声明
namespace local {
namespace {
int i;
}
}
local::i = 42;
- 未命名的命名空间取代文件的静态声明。
2. 使用命名空间成员
- 一个命名空间可以有好几个同义词或别名,所有别名都与命名空间原来的名字等价。
namespace cplusplus_primer {};
namespace primer = cplusplus_primer;
- 避免
using指示
3. 类、命名空间与作用域
- 对命名空间内部名字的查找遵循常规的查找规则:即由内向外依次查找每个外层作用域。外层作用域也可能是一个或多个嵌套的命名空间,直到最外层的全局命名空间查找过程终止。只有位于开放的块中且在使用点之前的名字才被考虑。
- 可以从函数的限定名与推断出查找名字时检查作用域的次序,限定名以相反次序指出被查找的作用域。
4. 重载与命名空间
using声明语句声明的是一个名字,而非特定的函数,也就是包括该函数的所有版本,都被引入到当前作用域中。
三、多重继承与虚继承
1. 多重继承
2. 类型转换与多个基类
3. 多重继承下的类作用域
- 当一个类拥有多个基类时,有可能出现派生类从两个或更多基类中继承了同名成员的情况。此时,不加前缀限定符直接使用该名字将引发二义性。
4. 虚继承
- 虚继承的目的是令某个类做出声明,承诺愿意共享它的基类。其中,共享的基类子对象成为虚基类。在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中都只包含唯一一个共享的虚基类子对象。
- 虚派生只影响从指定了虚基类的派生类中进一步派生出的类,它不会影响派生类本身。
5. 构造函数与虚继承
- h含有虚基类的对象的构造顺序与一般的顺序稍有区别:首先使用提供给最底层派生类构造函数的初始值初始化该对象的虚基类子部分,接下来按照直接基类在派生列表中出现的次序对其进行初始化。
- 虚基类总是先于非虚基类构造,与它们在继承体系中的次序和位置无关。
【C++】《C++ Primer 》第十八章的更多相关文章
- C++Primer 第十八章
//1.异常:待研究 //2.命名空间: // A:多个库将名字放置在全局命名空间中将引发命名空间污染. // B:命名空间为防止名字冲突提供了更加可控的机制.命名空间分割了全局命名空间,其中每个命名 ...
- 《Linux内核设计与实现》读书笔记 第十八章 调试
第十八章调试 18.1 准备开始 需要准备的东西: l 一个bug:大部分bug通常都不是行为可靠而且定义明确的 l 一个藏匿bug的内核版本:找出bug首先出现的版本 l 相 ...
- Python之路【第十八章】:Django基础
Django基本配置 Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Se ...
- 《Linux内核设计与实现》课本第十八章自学笔记——20135203齐岳
<Linux内核设计与实现>课本第十八章自学笔记 By20135203齐岳 通过打印来调试 printk()是内核提供的格式化打印函数,除了和C库提供的printf()函数功能相同外还有一 ...
- 《Linux命令行与shell脚本编程大全》 第十八章 学习笔记
第十八章:初识sed和gawk 文本处理 sed编辑器 sed编辑器可以基于输入到命令行的或是存储在命令文本文件中的命令来处理数据流中的数据. 它每次读取一行,用提供的编辑器命令匹配数据.按命令中指定 ...
- 第十八章 DjangoWeb开发框架
第十八章 DjangoWeb开发框架 第一课 内容概要: 1.JS正则 -登录注册验证 2.组件 1.BootStrap -css -js 学习BootStrap规则 2.jQueryUI -css ...
- Gradle 1.12用户指南翻译——第四十八章. Wrapper 插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- Gradle 1.12 翻译——第十八章. 日志
有关其他已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或访问:http://gradledoc.qiniudn.com ...
- Gradle 1.12用户指南翻译——第二十八章. Jetty 插件
其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...
随机推荐
- CCF统一省选 Day2 题解
此题解是教练给我的作业,AK了本场比赛的人,以及认为题目简单的人可以不必看 T1 算法一 暴力枚举对信号站顺序的不同排列,然后对代价取\(\min\)即可. 时间复杂度\(O(m! \cdot n)\ ...
- MySQL和sparkSQL合并行
表A 表B 从表A到表B MySQL 写法:select name, group_concat(score seperate ';') as score from A group by name sp ...
- js日期格式化-----总结
1. // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年(y)可以用 1-4 ...
- 优化Windows电脑常见方法,提高速度,释放硬盘C盘
开始,我们首先让电脑变得易于使用一,提高开机速度常见的使电脑变卡的原因是:一台电脑同时安装了多个杀毒软件.一台电脑安装多个杀毒软件不仅占用你电脑大量内存.有时甚至会产生冲突,这会导致电脑运行非常缓慢, ...
- 在Linux下下载RPM包
在Linux下下载RPM包,但是不安装 在工作中经常会遇到离线安装RPM包的情况,下面是下载RPM包的方法 # 使用yum下载RPM包 yum -y install --downloadonly &l ...
- mysql单机多实例配置
Windows上配置多个mysql实例,主要改下配置文件即可,mysql目录如下: my2中主要改两个配置内容 datadir = D:/Program Files/Mysql/mysql-5.7.2 ...
- js上 十九、综合案例
十九.综合案例 题目一: 封装一个函数equal(a1,a2),传入两个一维数组,判断两个数组是否包含相同的元素,如果相等,函数的返回值为true, 不相等,函数的返回值为false 1)例:arr1 ...
- [日常摸鱼]bzoj2875[NOI2012]随机数生成器-矩阵快速幂
好裸的矩阵快速幂-然而我一开始居然构造不出矩阵- 平常两个的情况都是拿相邻两项放在矩阵里拿去递推的-然后我就一直构造不出来-其实把矩阵下面弄成1就好了啊orz #include<cstdio&g ...
- fMRI数据分析学习笔记——常用工具
背景 在学习fMRI数据处理的过程中,通过其他的资料看到了别人推荐的有用的fMRI数据处理软件和小插件,在此记录一下,以便后期慢慢学习使用. 1.NeuroImaging Analysis Kit ( ...
- Networking from the container's point of view 笔记
Networking from the container's point of view Published portsThe type of network a container uses, w ...