第十八章 用于大型程序的工具
18.1 异常处理
1. 抛出异常
try、throw、catch(踹扔抓)
栈展开
寻找对应的catch语句的过程称之为栈展开
没找到相应的catch语句,程序会终止
栈展开过程中对象被自动销毁
栈展开可能会跳过某个局部块,此时该块里面的所有局部对象都将被销毁
析构函数与异常
析构函数不能抛出自己处理不了的异常,更近一步,析构函数最好不要抛出异常
异常对象
完全类型简单来说就是在throw语句使用之前已经定义好的类。
只声明没有定义就是不完全类型
不要抛出一个指向局部对象的指针,也不要返回局部对象的指针。
2. 异常捕获
查找匹配的处理代码
可以将派生类当成基类来用,当多个catch语句的类型之间存在继承关系的时候,我们应该把派生类放在前面处理(特殊化),而基类放在后面处理(一般化)。
重新抛出
当前catch语句块无法处理,重新抛出当前异常
只有当异常捕获是引用类型的时候,我们对参数所做的改变才会被保留并继续传播
捕获所有异常的处理代码
catch(…)
3. 函数try语句块与构造函数
为了解决在构造函数初始值列表抛出的异常,使用函数try语句块
try在初始化列表之前,空函数体,catch在空函数体之后
4. noexcept异常说明
预先告诉编译器某个函数不会抛出异常,修饰符放在后面
违反异常说明
noexcept修饰的函数抛出了异常,程序会自动终止
异常说明的实参
noexcept运算符
表示给定表达式是否会抛出异常
异常说明与指针、虚函数和拷贝控制
一个说明函数可能会抛出异常的函数指针可以指向任何函数。而一个说明函数不会抛出异常的函数指针只能指向不会抛出异常的函数。
虚函数的不会抛出异常承诺是继承的
5. 异常类层次
18.2 命名空间
1. 命名空间定义
namespace和一对花括号,命名空间结束无须分号
每个命名空间都是一个作用域
使用域访问符指定访问哪一个命名空间里面的哪一个成员
命名空间的定义可以是不连续的
头文件和命名空间
一般不把#include放在命名空间内部。如果这样做,隐含的意思就是把头文件中所有的名字都定义成了该命名空间的成员。这样会污染空间
全局命名空间
隐式的被定义。使用域访问符,不指定命名空间的名字来访问。
嵌套的命名空间
内联命名空间
内联命名空间中的名字可以被外层命名空间直接使用
未命名的命名空间
无名命名空间中的成员可以直接使用
只需要访问到外层,就可以拿到里层的变量。此处只需要访问到local命名空间,就能得到无名命名空间的变量。
2. 使用命名空间成员
使用using声明引入
命名空间的别名
using声明:扼要概述
一条using声明语句一次只引入命名空间的一个成员。
using namespace::member;
namespace表示某个命名空间的名字
member表示该命名空间里面的某个成员名字
using指示
using指示一次引入一个命名空间
using namespace xx;
xx表示命名空间的名字
using指示示例
使用域访问符指定应该访问哪一个变量
头文件与using声明或指示
头文件不要引入using指示或声明,要在函数或命名空间里面使用
避免using指示
3. 类、命名空间与作用域
实参相关的查找与类类型实参
函数实参是类类型,会引入实参类所在的命名空间
友元声明与实参相关的查找
函数接收一个类的对象,并且该函数在参数类里面作为友元声明。
则在使用时仅通过实参类也能找到函数的声明,函数声明由参数类的命名空间引入
4. 重载与命名空间
using声明或using指示显式引入的命名空间
函数参数类隐式引入的命名空间
与实参查找相关的查找与重载
函数参数是派生类,不仅引入了派生类的命名空间,也引入了基类的命名空间
重载与using声明
using声明将会引入同名的所有重载函数。
重载与using指示
引入命名空间,命名空间中如果有与当前空间相同的函数,则不会产生错误。只需在使用时指明使用的是那个函数即可。
18.3 多重继承与虚继承
继承多个基类
1. 多重继承
在派生列表中可以列出多个基类,表示多重继承
多重继承的派生类从每个基类中继承状态
包含有多个基类的数据成员
派生类构造函数初始化所有基类
同样是遵循分层的思想,派生类不直接初始化基类成员,而是调用基类构造函数初始化基类成员。
继承的构造函数与多重继承
如果一个类从多个基类中继承了相同的构造函数,则这个类必须为该构造函数定义它自己的版本
上图中,D1继承了Base1和Base2的两个相同的构造函数,会引发冲突。
析构函数与多重继承
2. 类型转换与多个基类
多重继承的情况下,也可以让基类的指针或引用指向派生类对象
重载可能会出现二义性:两个接受基类实参的函数,传入一个派生类对象
基于指针类型或引用类型的查找
3. 多重继承下的类作用域
4. 虚继承
可能会出现一个派生类多次继承同一个基类,在默认情况下派生类将会包含多个基类子对象。
使用虚继承机制指定派生类只能包含一个虚基类子对象
使用虚基类
在基类上将其指定为虚基类,在继承时就会自动进行虚继承
虚基类成员的可见性
5. 构造函数与虚继承
虚继承对象的构造方法
优先构造虚基类