logo资料库

c++ prime 中文版.pdf

第1页 / 共1043页
第2页 / 共1043页
第3页 / 共1043页
第4页 / 共1043页
第5页 / 共1043页
第6页 / 共1043页
第7页 / 共1043页
第8页 / 共1043页
资料共1043页,剩余部分请下载后查看
译序
前言
第一篇 C++概述
第1章 开始
1.1 问题的解决
1.2 C++程序
1.3 预处理器指示符
1.4 注释
1.5 输入/输出初步
1.5.1 文件输入和输出
第2章 C++浏览
2.1 内置数组数据类型
2.2 动态内存分配和指针
2.3 基于对象的设计
2.4 面向对象的设计
2.5 泛型设计
2.6 基于异常的设计
2.7 用其他名字来命名数组
2.8 标准数组——向量
第二篇 基本语言
第3章 C++数据类型
3.1 文字常量
3.2 变量
3.2.2 变量名
3.2.3 对象的定义
3.3 指针类型
3.4 字符串类型
3.4.1 C风格字符串
3.4.2 字符串类型
3.5 const限定修饰符
3.6 引用类型
3.7 布尔类型
3.8 枚举类型
3.9 数组类型
3.9.1 多维数组
3.9.2 数组与指针类型的关系
3.10 vector容器类型
3.11 复数类型
3.12 typedef名字
3.13 volatile限定修饰符
3.14 pair类型
3.15 类类型
第4章 表达式
4.1 什么是表达式?
4.2 算术操作符
4.3 等于、关系和逻辑操作符
4.4 赋值操作符
4.5 递增和递减操作符
4.6 复数操作
4.7 条件操作符
4.6 sizeof操作符
4.9 new和delete表达式
4.10 逗号操作符
4.11 位操作符
4.12 bitset操作
4.13 优先级
4.14 类型转换
4.14.1 隐式类型转换
4.14.2 算术转换
4.14.3 显式转换
4.14.4 旧式强制类型转换
4.15 栈类实例
第5章 语句
5.1 简单语句和复合语句
5.2 声明语句
5.3 if语句
5.4 switch语句
5.5 for循环语句
5.6 while语句
5.7 do while语句
5.8 break语句
5.9 continue语句
5.10 goto语句
5.11 链表示例
5.11.1 给出一个通用链表类
第6章 抽象容器类型
6.1 我们的文本查询系统
6.2 vector还是list?
6.3 vector怎样自己增长
6.4 定义一个顺序容器
6.5 迭代器
6.6 顺序容器操作
6.7 存储文本行
6.8 找到一个子串
6.9 处理标点符号
6.10 任意其他格式的字符串
6.11 其他string操作
6.12 生成文本位置map
6.12.2 查找并获取map中的元素
6.12.3 对map进行迭代
6.12.4 单词转换map
6.12.5 从map中删除元素
6.13 创建单词排除集
6.13.1 定义set并放入元素
6.13.2 搜索一个元素
6.13.3 迭代一个set对象
6.14 完整的程序
6.15 multimap和multiset
6.16 栈
6.17 队列和优先级队列
6.18 回顾iStack类
第三篇 基于过程的程序设计
第7章 函数
7.1 概述
7.2 函数原型
7.2.1 函数返回类型
7.2.2 函数参数表
7.2.3 参数类型检查
7.3 参数传递
7.3.1 引用参数
7.3.2 引用和指针参数的关系
7.3.3 数组参数
7.3.4 抽象容器类型参数
7.3.5 缺省实参
7.3.6 省略号(ellipsis)
7.4 返回一个值
7.4.1 参数和返回值与全局对象
7.5 递归
7.6 inline函数
7.7 链接指示符:extern“C”
7.8 main():处理命令行选项
7.8.1 一个处理命令行的类
7.9 指向函数的指针※
7.9.1 指向函数的指针的类型
7.9.2 初始化和赋值
7.9.3 调用
7.9.4 函数指针的数组
7.9.5 参数和返回类型
7.9.6 指向extern "C"函数的指针
第8章 域和生命期
8.1 域
8.1.1 局部域
8.2 全局对象和函数
8.2.1 声明和定义
8.2.2 不同文件之间声明的匹配
8.2.3 谈谈头文件
8.3 局部对象
8.3.1 自动对象
8.3.2 寄存器自动对象
8.3.3 静态局部对象
8.4 动态分配的对象
8.4.1 单个对象的动态分配与释放
8.4.2 auto_ptr ※
8.4.3 数组的动态分配与释放
8.4.4 常量对象的动态分配与释放
8.4.5 定位new表达式
8.5 名字空间定义 ※
8.5.1 名字空间定义
8.5.2 域操作符(::)
8.5.3 嵌套名字空间
8.5.4 名字空间成员定义
8.5.5 ODR和名字空间成员
8.5.6 未命名的名字空间
8.6 使用名字空间成员 ※
8.6.1 名字空间别名
8.6.2 using 声明
8.6.3 using指示符
8.6.4 标准名字空间std
第9章 重载函数
9.1 重载函数声明
9.1.1 为什么要重载一个函数名
9.1.2 怎样重载一个函数名
9.1.3 何时不重载一个函数名
9.1.4 重载与域 ※
9.1.5 extern "c" 和重载函数 ※
9.1.6 指向重载函数的指针 ※
9.1.7 类型安全链接 ※
9.2 重载解析的三个步骤
9.3 参数类型转换 ※
9.3.1 精确匹配的细节
9.3.2 提升的细节
9.3.3 标准转换的细节
9.3.4 引用
9.4 函数重载解析细节 ※
9.4.1 候选函数
9.4.2 可行函数
9.4.3 最佳可行函数
9.4.4 缺省实参
第10章 函数模板
10.1 函数模板定义
10.2 函数模板实例化
10.3 模板实参推演 ※
10.4 显式模板实参 ※
10.5 模板编译模式 ※
10.5.1 包含编译模式
10.5.2 分离编译模式
10.5.3 显式实例化声明
10.6 模板显式特化 ※
10.7 重载函数模板 ※
10.8 考虑模板函数实例的重载解析 ※
10.9 模板定义中的名字解析 ※
10.10 名字空间和函数模板 ※
10.11 函数模板示例
第11章 异常处理
11.1 抛出异常
11.2 try块
11.3 捕获异常
11.3.1 异常对象
11.3.2 栈展开
11.3.3 重新抛出
11.3.4 catch-all处理代码
11.4 异常规范
11.4.1 异常规范与函数指针
11.5 异常与设计事项
第12章 泛型算法
12.1 概述
12.2 使用泛型算法
12.3 函数对象
12.3.1 预定义函数对象
12.3.2 算术函数对象
12.3.3 关系函数对象
12.3.4 逻辑函数对象
12.3.5 函数对象的函数适配器
12.3.6 实现函数对象
12.4 回顾iterator
12.4.1 插入iterator
12.4.2 反向iterator
12.4.3 iostream iterator
12.4.4 istream_iterator
12.4.5 ostream_iterator
12.4.6 五种 iterator
12.5 泛型算法
12.5.1 查找算法
12.5.2 排序和通用整序算法
12.5.3 删除和替换算法
12.5.4 排列组合算法
12.5.5 算术算法
12.5.6 生成和异变算法
12.5.7 关系算法
12.5.8 集合算法
12.5.9 堆算法
12.6 何时不用泛型算法
12.6.1 list::merge()
12.6.2 list::remove()
12.6.3 list::remove_if()
12.6.4 list::reverse()
12.6.5 list::sort()
12.6.6 list::splice()
12.6.7 list::unique()
第四篇 基于对象的程序设计
第13章 类
13.1 类定义
13.1.1 数据成员
13.1.2 成员函数
13.1.3 成员访问
13.1.4 友元
13.1.5 类声明和类定义
13.2 类对象
13.3 类成员函数
13.3.1 inline和非inline成员函数
13.3.2 访问类成员
13.3.3 私有与公有成员函数
13.3.4 特殊的成员函数
13.3.5 const和volatile成员函数
13.3.6 mutable数据成员
13.4 隐含的this指针
13.4.1 何时使用this指针
13.5 静态类成员
13.5.1 静态成员函数
13.6 指向类成员的指针
13.6.1 类成员的类型
13.6.2 使用指向类成员的指针
13.6.3 静态类成员的指针
13.7 联合:一种节省空间的类
13.8 位域(bit-field):一种节省空间的成员
13.9 类域 ※
13.9.1 类域中的名字解析
13.10 嵌套类
13.10.1 在嵌套类域中的名字解析
13.11 作为名字空间成员的类 ※
13.12 局部类 ※
第14章 类的初始化、赋值和析构
14.1 类的初始化
14.2 类的构造函数
14.2.1 缺省构造函数
14.2.2 限制对象创建
14.2.3 拷贝构造函数
14.3 类的析构函数
14.3.1 显式的析构调用
14.3.2 可能出现的程序代码膨胀
14.4 类对象数组和vector
14.4.1 堆数组的初始化 ※
14.4.2 类对象的vector
14.5 成员初始化表
14.6 按成员初始化 ※
14.6.1 成员类对象的初始化
14.7 按成员赋值 ※
14.8 效率问题 ※
第15章 重载操作符和用户定义的转换
15.1 操作符重载
15.1.1 类成员与非成员
15.1.2 重载操作符的名字
15.2 友元
15.3 操作符=
15.4 操作符[]
15.5 操作符operator()
15.6 操作符->
15.7 操作符++和--
15.8 操作符new和delete
15.8.1 数组操作符new[]和delete[]
15.8.2 定位操作符new()和delete()
15.9 用户定义的转换
15.9.1 转换函数
15.9.2 用构造函数作为转换函数
15.10 选择一个转换 ※
15.10.1 函数重载解析——回顾
15.10.2 侯选函数
15.10.3 类域中的函数所调用的候选函数
15.10.4 对用户定义的转换序列划分等级
15.11 重载解析和成员函数 ※
15.11.1 重载成员函数的声明
15.11.2 候选函数
15.11.3 可行函数
15.12 重载解析和操作符 ※
15.12.1 候选的操作符函数
15.12.2 可行函数
15.12.3 二义性
第16章 类 模 板
16.1 类模板定义
16.1.1 Queue和QueueItem类模板的定义
16.2 类模板实例化
16.2.1 非类型参数的模板实参
16.3 类模板的成员函数
16.3.1 Queue和QueueItem模板成员函数
16.4 类模板中的友元声明
16.4.1 Queue和QueueItem的友元声明
16.5 类模板的静态数据成员
16.6 类模板的嵌套类型
16.7 成员模板 ※
16.8 类模板和编译模式 ※
16.8.1 包含编译模式
16.8.2 分离编译模式
16.8.3 显式实例声明
16.9 类模板特化 ※
16.10 类模板部分特化 ※
16.11 类模板中的名字解析 ※
16.12 名字空间和类模板 ※
16.13 模板数组类
第五篇 面向对象的程序设计
第17章 类继承和子类型
17.1 定义一个类层次结构
17.1.1 面向对象的设计
17.2 确定层次的成员
17.2.1 定义基类
17.2.2 定义派生类
17.2.3 小结
17.3 基类成员访问
17.4 基类和派生类的构造
17.4.1 基类构造函数
17.4.2 派生类构造函数
17.4.3 另外一个类层次结构
17.4.4 迟缓型错误检测(Lazy error detection)
17.4.5 析构函数
17.5 基类和派生类虚拟函数
17.5.1 虚拟的输入/输出
17.5.2 纯虚拟函数
17.5.3 虚拟函数的静态调用
17.5.4 虚拟函数和缺省实参
17.5.5 虚拟析构函数
17.5.6 eval()虚拟函数
17.5.7 虚拟new操作符
17.5.8 虚拟函数、构造函数和析构函数
17.6 按成员初始化和赋值 ※
17.7 UserQuery管理类
17.7.1 定义UserQuery类
17.8 组合起来
第18章 多继承和虚拟继承
18.1 准备阶段
18.2 多继承
18.3 public、private和protected继承
18.3.1 继承与组合(composition)
18.3.2 免除(exempting)个别成员的私有继承影响
18.3.3 protected继承
18.3.4 对象组合
18.4 继承下的类域
18.4.1 多继承下的类域
18.5 虚拟继承 ※
18.5.1 虚拟基类声明
18.5.2 特殊的初始化语义
18.5.3 构造函数与析构函数顺序
18.5.4 虚拟基类成员的可视性
18.6 多继承及虚拟继承实例 ※
18.6.1 带有范围检查的Array派生类
18.6.2 排序的Array派生类
18.6.3 多重派生的Array类
第19章 C++中继承的用法
19.1 RTTI
19.1.1 dynamic_cast操作符
19.1.2 typeid操作符
19.1.3 type_info类
19.2 异常和继承
19.2.1 定义为类层次结构的异常
19.2.2 抛出类类型的异常
19.2.3 处理类类型的异常
19.2.4 异常对象和虚拟函数
19.2.5 栈展开和析构函数调用
19.2.6 异常规范
19.2.7 构造函数和函数try块
19.2.8 C++标准库的异常类层次结构
19.3 重载解析过程和继承 ※
19.3.1 候选函数
19.3.2 可行函数和用户定义的转换序列
19.3.3 最佳可行函数
第20章 iostream库
20.1 输出操作符<<
20.2 输入
20.2.1 字符串输入
20.3 其他输入/输出操作符
20.4 重载输出操作符<<
20.5 重载输入操作符>>
20.6 文件输入和输出
20.7 条件状态
20.8 string流
20.9 格式状态
20.10 强类型库
泛型算法(按字母排序)
accumulate()
adjacent_difference()
adjacent_find()
binary_search()
copy()
copy_backward()
count()
count_if()
equal()
equal_range()
fill()
fill_n()
find()
find_if()
find_end()
find_first_of()
for_each()
generate()
generate_n()
includes()
inner_product()
inplace_merge()
iter_swap()
lexicographical_compare()
lower_bound()
max()
max_element()
min()
min_element()
merge()
mismatch()
next_permutation()
nnth_element()
partial_sort()
partial_sort_copy()
partial_sum()
prev_permutation()
random_shuffle()
remove()
remove_copy()
remove_if()
remove_copy_if()
replace()
replace_copy()
replace_if()
replace_copy_if()
reverse()
reverse_copy()
rotate()
rotate_copy()
search()
search_n()
set_difference()
set_intersection()
set_symmetric_difference()
set_union()
sort()
stable_partition()
stable_sort()
swap()
swap_range()
transform()
unique()
unique_copy()
upper_bound()
堆算法
make_heap()
pop_heap()
push_heap()
sort_heap()
英汉对照索引
凡例
符号
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
深入 系列 Primer 第三版 中中文文版版 潘爱民 张丽 译 Stanley B Lippman J o s é e L a j o i e 著 Addison-Wesley 中 国 电 力 出 版 社 www.infopower.com.cn
译序 这是我心仪已久的一本书 我相信很多读者也有同样的感受 在所有的编程语言中 C++可以说是最为复杂的 它既是一门传统的编程语言 也是一门 新的编程语言 说它是一门传统语言 是因为 C++诞生已将近 20 年的历史了 特别是最近 10 年来 C++得到了快速的发展 C++是计算机软件领域中覆盖面最为广阔的编程语言 并且 与 C++相关的智力投入也是其他任何一门语言所无法比拟的 人们对于 C++的研究已经远远超出 了对于一门编程语言所应有的关注 所以 现在的 C++已经非常成熟 有大量的资源 文档 书籍 源代码等等 可供我们使用 说 C++是一门新的编程语言 是因为在 1998 年 C++由 ISO International Standards Organization 完成了标准化 从此 C++领域有了统一的标准 所 有的编译器都将向标准靠拢 或者说 与标准兼容 这有利于我们写出可移植的 C++代码来 同时 C++标准也统一了 C++标准库 为 C++用户提供了最为基本的基础设施 C++经历了多年 的发展 终于有了一个相对稳定的版本 所以 我们应该用一种新的眼光来看待 C++ 而不再 简单地把 C++认为是 C 语言的超集 本书正是新版本 C++的写照 通过本书 你可以重新审视 C++语言 这是我翻译过程中最为真切的体会 它纠正了我过去对于 C++语言的一些误解 虽 然我从 1993 年开始就一直在使用 C++ 但是直到阅读了这本书之后 我才从真正意义上全面 地认识了 C++语言 本书的权威性无需我多说 看看本书原著的前言 了解了两位作者的背景之后 你就可以 知道 这本书是经验和标准的完美结合 Stanley Lippman 从 1984 年开始一直从事 C++方面的 工作 在 C++的实现与应用方面有着丰富的经验 本书前两个版本的成功也证明了他在阐释 C++语言方面的独到之处 Josée Lajoie 从 1990 年开始成为 C++标准委员会的一名成员 并且 承担了很重要的职务 由于她的参与 毫无疑问 本书一定是与标准兼容的 讲述 C++的书非常多 并且不乏优秀和经典之作 在如此众多的 C++书籍中 本书仍具有 不可替代的地位 我想主要的原因在于本书具有以下几个特色 l 内容广阔 从本书的规模 厚度 就可以看出这一点 C++语言融入了大量优秀的特 性 其内容的丰富程度已经远非 C 语言所能及 在所有的 C++书籍中 本书的覆盖面是最为广 阔的 从最基本的 C++程序设计 到面向对象程序设计 以及基于模板的程序设计 面面俱到 而且讲解细致入微 值得仔细品味 2 许多实际的范例程序 纯粹的技术讲解总是非常枯燥的 但是阅读本书并不感觉枯燥 因为作者在介绍每一部分内容的时候都结合一个实际的例子 读者通过这些例子能够很容易地 掌握相应的技术要点 并且看到每一种技术的实际用法 这是本书之所以引人入胜的重要原因 之一 3 叙述内容的安排 C++是一门多风格的程序设计语言 multi-paradigm Programming language 不仅支持面向对象程序设计 也支持其他的程序设计思想 本书的叙述结构正体现 了 C++的这种特点 作者从程序设计思想的角度分别讲述了 C++的各种语言要素 便读者比较
II 译序 4 与编译器无关 遵从 C++标准 本书的内容并不特定于某一个 C++编译器实现 而 容易抓住 C++语言的本质特征 是适用于所有与 C++标准兼容的编译器 作者在讲解过程中也指出了编译器的一些内部考虑 例如 编译器如何在各种上下文环境中解析重载函数 如何处理除式类型转换 等等 这些内 容有利于加深读者对 C++的理解 5 配套的练习 在每一节讲解之后 作者给出了一些练习 这些练习反映了这一节的中 心内容 读者通过这些练习可以巩固所学的知识 所以 本书也可以被用作教材 用于系统全 面地学习 C++语言 虽然本书书名 C++ Primer 的中文含义是 C++初级读本 但是它绝对不是一本很轻 松的入门教材 特别是关于名字空间 函数重载解析过程 模板机制和泛型算法 generic algorithms 等内容并不是一个 C++初学者能够很快掌握的 如果你以前没有看过其他的 C++ 书籍 那么可能需要反复阅读多遍才能掌握本书讲述的内容 如果你已经有了 C++的基础 比 如 已经看过其他的 C++入门书籍 那么阅读本书可以让你快速掌握 C++的要点 如果你是 一名有多年 C++实践经验的程序员 那么阅读本书可以让你重新理解 C++ 总之 这是一本很 好的学习和参考书籍 值得你反复阅读 但是 正如书名所指示的 它不是一本高级书籍 按 照我个人理解 它的技术水准应该在中等偏深一点的层次上 本书的翻译工作由我和张丽共同完成 张丽完成了初稿的翻译工作 我做了第二遍翻译检 查工作 书中每一句话我都认真检查过 个别地方还修改了原著的一些错误 C++中有些术语 还没有统一的中文说法 对于这些术语的处理 我们尽可能地做到符合中文的语言习惯 读者 可以参考本书最后所附的英汉对照索引 这份索引是由中国电力出版社的诸位编辑手工制作完 成的 他们是刘江 朱恩从 陈维宁 程璐 关敏 刘君 夏平 宋宏 姚贵胜 常虹 乔晶 阎宏 感谢他 她 们的辛勤劳动 在翻译过程中 不断收到读者来信或者来电询问这本书的出版情况 我理解读者对于一本 好书的迫切心情 我的想法是 有关 C++的书籍和资料如此之多 所以 学习 C++不一定非要 阅读这本书 但是它可以加快你学习的步伐 并且帮助你深入而全面地理解 C++ 既然你已经 看到了这本书 那就不要错过吧 这本书不会让你失望的 我坚信这一点 潘爱民 北京大学燕北园
前言 本书第二版和第三版之间的变化非常大 其中最值得注意的是 C++已经通过了国际标 准化 这不但为语言增加了新的特性 比如异常处理 运行时刻类型识别 RTTI 名字空 间 内置布尔数据类型 新的强制转换方式 而且还大量修改并扩展了现有的特性 比如模 板 template 支持面向对象 object-oriented 和基于对象 object-based 程序设计所需 要的类 class 机制 嵌套类型以及重载函数的解析机制 也许更重要的是 一个覆盖面非 常广阔的库现在成了标准 C++的一部分 其中包括以前称为 STL 标准模板库 的内容 新 的 string 类型 一组顺序和关联容器类型 比如 vector list map 和 set 以及在这些类型 上进行操作的一组可扩展的泛型算法 generic algorithm 都是这个新标准库的特性 本书 不但包括了许多新的资料 而且还阐述了怎样在 C++中进行程序设计的新的思考方法 简而 言之 实际上 不但 C++已经被重新创造 本书第三版也是如此 在第三版中 不但对语言的处理方式发生了根本的变化 而且作者本身也发生了变化 首先 我们的人数已经加倍 而且 我们的写作过程也已经国际化了 尽管我们还牢牢扎根 于北美大陆 Stan Lippman 是美国人 Josée Lajoie 是加拿大人 最后 这种双作者关系也 反映了 C++团体的两类主要活动 Stan 现在正在迪斯尼动画公司 Walt Disney Feature Animation *致力于以 C++为基础的 3D 计算机图形和动画应用 而 Josée 正专心于 C++的定 义与实现 同时她也是 C++标准的核心语言小组的主席** 以及 IBM 加拿大实验室的 C++编 译器组的成员 Stan 是 Bell 实验室中与 Bjarne Stroustrup C++的发明者 一起工作的早期成员之一 从 1984 年开始一直从事 C++方面的工作 Stan 曾经致力于原始 C++编译器 cfront 的各种实 现 从 1986 年的版本 1.1 到版本 3.0 并领导了 2.1 和 3.0 版本的开发组 之后 他参与了 Stroustrup 领导的 Foundation Research Project 项目中关于程序设计环境的对象模型部分 Josée 作为 IBM 加拿大实验室 C++编译器组的成员已经有八年时间了 从 1990 年开始她 成为 C++标准委员会的成员 她曾经担任委员会的副主席三年 日前担任核心语言小组委员 会的主席已经达四年之久 本书第三版是一个大幅修订的版本 不仅反映了语言的变化和扩展 也反映了作者洞察 力和经验的变化 * Stan Lippman 现已受雇于 Microsoft 成为 Visual C++ .Net 的架构设计师 ** Josée Lajoie 现正在滑铁卢大学攻读硕士学位.已不再担任该委员会的主席 现任主席为 Sun 公司的 Steve Clamage
IV 译序 本书的结构 本书为 C++国际标准进行了全面的介绍 在此意义上 它是一个初级读本 primer 它提供了一种指导性的方法来描述 C++语言 但是 它也为 C++语言提供了一种简单而温 和的描述 从这个角度来看 它不是一本初级读物 C++语言的程序设计要素 比如异常 处理 容器类型 面向对象的程序设计等等 都在解决特定问题或程序设计任务的上下文环 境中展示出来 C++语言的规则 比如重载函数调用的解析过程以及在面向对象程序设计下 支持的类型转换 本书都有广泛的论述 这似乎超出了一本初级读本的范畴 我们相信 为 了加强读者对于 C++语言的理解 覆盖这些内容是必要的 对于这些材料 读者应该不时地 回头翻阅 而不是一次消化了事 如果开始的时候你发现这些内容比较难以接受或者过于枯 燥 请把它们放到一边 以后再回头来看——我们为这样的章节加上了特殊的记号 阅读本书不需要具备 C 语言的知识 但是 熟悉某些现代的结构化语言会使学习进展更 快一些 本书的意图是作为学习 C++的第一本书 而不是学习程序设计的第一本书 为了确 保这一点 我们会以一个公共的词汇表作为开始 然而 开始的章节涵盖了一些基本的概念 比如循环语句和变量等 有些读者可能会觉得这些概念太浅显了 不必担心 深层的内容很 快就会看到 C++的许多威力来自于它对程序设计新方法的支持 以及对程序设计问题的思考方式 因此 要想有效地学习使用 C++ 不要只想简单地学会一组新的语法和语义 为了使这种学 习更加容易 本书将围绕一系列可扩展的例子来组织内容 这些例子被用来介绍各种语言特 性的细节 同时也说明了这些语言特性的动机所在 当我们在一个完整例子的上下文环境中 学习语言特性时 对这些特性为什么会有用处也就变得很清楚了 它会使我们对于 何时以 及怎样在实际的问题解决过程中使用这些特性 有一些感觉 另外 把焦点放在例子上 可 使读者能够尽早地使用一些概念 随着读者的知识基础被建立起来之后 这些概念会进一步 完整地解释清楚 本书前面的例子含有 C++基本概念的简单用法 读者可以先领略一下 C++ 中程序设计的概貌 而不要求完全理解 C++程序设计和实现的细节 第 1 章和第 2 章形成了一个独立完整的 C++介绍和概述 第一篇的目的是使我们快速地 理解 C++支持的概念和语言设施 以及编写和执行一个程序所需要的基础知识 读完这部分 内容之后 你应该对 C++语言有了一些认识 但是还谈不上真正理解 C++ 这就够了 那是 本书余下部分的目的 第 1 章向我们介绍了语言的基本元素 内置数据类型 变量 表达式 语句以及函数 它将介绍一个最小的 合法的 C++程序 简要讨论编译程序的过程 介绍所谓的预处理器 preprocessor 以及对输入和输出的支持 它给出了多个简单但却完整的 C++程序 鼓励 读者亲自编译并执行这些程序 第 2 章介绍了 C++是如何通过类机制 为基于对象和面向对 象的程序设计提供支持的 同时通过数组抽象的演化过程来说明这些设计思想 另外 它简 要介绍了模板 名字空间 异常处理 以及标准库为一般容器类型和泛型程序设计提供的支 持 这一章的进度比较快 有些读者可能会觉得难以接受 如果是这样 我们建议你跳过这 一章 以后再回过头来看它 C++的基础是各种设施 它们使用户能够通过定义新的数据类型来扩展语言本身 这些
V 译序 新类型可以具有与内置类型一样的灵活性和简单性 掌握这些设施的第一步是理解基本语言 本身 第 3 章到第 6 章 第二篇 在这个层次上介绍了 C++语言 第 3 章介绍了 C++语言预定义的内置和复合数据类型 以及 C++标准库提供的 string complex vector 类数据类型 这些类型构成了所有程序的基石 第 4 章详细讨论了 C++语言 支持的表达式 比如算术 关系 赋值表达式 语句是 C++程序中最小的独立单元 它是第 5 章的主题 C++标准库提供的容器类型是第 6 章的焦点 我们不是简单地列出所有可用的 操作 而是通过一个文本查询系统的实现 来说明这些容器类型的设计和用法 第 7 章到第 12 章 第三篇 集中在 C++为基于过程化的程序设计所提供的支持上 第 7 章介绍 C++函数机制 函数封装了一组操作 它们通常形成一项单一的任务 如 print() 名 字后面的括号表明它是一个函数 关于程序域和变量生命期的概念 以及名字空间设施的 讨论是第 8 章的主题 第 9 章扩展了第 7 章中引入的关于函数的讨论 介绍了函数的重载 函数重载允许多个函数实例 它们提供一个公共的操作 共享一个公共的名字 但是 要求 不同的实现代码 例如 我们可以定义一组 print()函数来输出不同类型的数据 第 10 章介 绍和说明函数模板的用法 函数模板为自动生成多个函数实例 可能是无限多个 提供了一 种规范描述 prescription 这些函数实例的类型不同 但实现方式保持不变 C++支持异常处理设施 异常表示的是一个没有预料到的程序行为 比如所有可用的程 序内存耗尽 出现异常情况的程序部分会抛出一个异常——即程序的其他部分都可以访问到 程序中的某个函数必须捕获这个异常并做一些必要的动作 对于异常处理的讨论跨越了两章 第 11 章用一个简单的例子介绍了异常处理的基本语法和用法 该例子捕获和抛出一个类类型 class type 的异常 因为在我们的程序中 实际被处理的异常通常是一个面向对象类层次 结构的类对象 所以 关于怎样抛出和处理异常的讨论一直继续到第 19 章 也就是在介绍面 向对象程序设计之后 第 12 章介绍标准库提供的泛型算法集合 看一看它们怎样和第 6 章的容器类型以及内 置数组类型互相作用 这一章以一个使用泛型算法的程序设计作为开始 第 6 章介绍的 iterator 迭代器 在第 12 章将进一步讨论 因为它们为泛型算法与实际容器的绑定提供了粘合剂 这一章也介绍并解释了函数对象的概念 函数对象使我们能够为泛型算法中用到的操作符 比 如等于或小于操作符 提供另一种可替换的语义 关于泛型算法在附录中有详细说明 并带 有用法的示例 第 13 章到第 16 章 第四篇 的焦点集中在基于对象的程序设计上——即创建独立的抽 象数据类型的那些类设施的定义和用法 通过创建新的类型来描述问题域 C++允许程序员 在写应用程序时可以不用关心各种乏味的簿记工作 应用程序的基本类型可以只被实现一次 而多次被重用 这使程序员能够将注意力集中在问题本身 而不是实现细节上 这些封装数 据的设施可以极大地简化应用程序的后续维护和改进工作 第 13 章集中在一般的类机制上 怎样定义一个类 信息隐藏的概念 即 把类的公有 接口同私有实现分离 以及怎样定义并封装一个类的对象实例 这一章还有关于类域 嵌 套类 类作为名字空间成员的讨论 第 14 章详细讨论 C++为类对象的初始化 析构以及赋值而提供的特殊支持 为了支持 这些特殊的行为 需要使用一些特殊的成员函数 分别是构造函数 析构函数和拷贝赋值操 作符 这一章我们还将看一看按成员初始化和拷贝的主题 即指一个类对象被初始化为或者
VI 译序 赋值为该类的另一个对象 以及为了有效地支持按成员初始化和拷贝而提出的命名返回值 named return value 扩展 18 第 15 章将介绍类特有的操作符重载 首先给出一般的概念和设计考虑 然后介绍一些 特殊的操作符 如赋值 下标 调用以及类特有的 new 和 delete 操作符 这一章还介绍了类 的友元 它对一个类具有特殊的访问特权 及其必要性 然后讨论用户定义的转换 包括底 层的概念和用法的扩展实例 这一章还详细讨论了函数重载解析的规则 并带有代码示例说 明 类模板是第 16 章的主题 类模板是用来创建类的规范描述 其中的类包含一个或多个 参数化的类型或值 例如 一个 vector 类可以对内含的元素类型进行参数化 一个 buffer 类 可以对内含的元素类型以及缓冲区的大小进行参数化 更复杂的用法 比如在分布式计算中 IPC 接口 寻址接口 同步接口等 都可以被参数化 这一章讨论了怎样定义类模板 怎样 创建一个类模板特定类型的实例 怎样定义类模板的成员 成员函数 静态成员和嵌套类型 以及怎样用类模板来组织我们的程序 最后以一个扩展的类模板的例子作为结束 面向对象的程序设计和 C++的支持机制是第 17 19 和 20 章 第五篇 的主题 第 17 章介绍了 C++对于面向对象程序设计主要要素的支持 继承和动态绑定 在面向对象的程 序设计中 用父/子关系 也称类型/子类型关系 来定义 有共同行为的各个类 类不用 重新实现共享特性 它可以继承了父类的数据和操作 子类或者子类型只针对它与父类不同 的地方进行设计 例如 我们可以定义一个父类 Employee 以及两个子类型 TemporaryEmpl 和 Manager 这些子类型继承了 Employee 的全部行为 它们只实现自己特有的行为 继承的第二个方面 称为多态性 是指父类型具有 引用由它派生的任何子类型 的能 力 例如 一个 Employee 可以指向自己的类型 也可以指向 TemporaryEmpl 或者 Manager 动态绑定是指 在运行时刻根据多态对象的实际类型来确定应该执行哪个操作 的解析能力 在 C++中 这是通过虚拟函数机制来处理的 第 17 章介绍了面向对象程序设计的基本特性 这一章说明了如何设计和实现一个 Query 类层次结构 用来支持第 6 章实现的文本查询系统 第 18 章介绍更为复杂的继承层次结构 多继承和虚拟继承机制使得这样的层次结构成 为可能 这一章利用多继承和虚拟继承 把第 16 章的模板类例子扩展成一个三层的类模板层 次结构 第 19 章介绍 RTTI 运行时刻类型识别 设施 使用 RTTI 我们的程序在执行过程中可 以查询一个多态类对象的类型 例如 我们可以询问一个 Employee 对象 它是否实际指向 一个 Manager 类型 另外 第 19 章回顾了异常处理机制 讨论了标准库的异常类层次机构 并说明了如何定义和处理我们自己的异常类层次结构 这一章也深入讨论了在继承机制下重 载函数的解析过程 第 20 章详细说明了如何使用 C++的 iostream 输入/输出库 它通过例子说明了一般的数 据输入和输出 说明了如何定义类特有的输入输出操作符实例 如何辨别和设置条件状态 如何对数据进行格式化 iostream 库是一个用虚拟继承和多继承实现的类层次结构 本书以一个附录作为结束 附录给出了每个泛型算法的简短讨论和程序例子 这些算法 按字母排序 以便参考 最后 我们要说的是 无论谁写了一本书 他所省略掉的 往往与他所讲述的内容一样
VII 译序 重要 C++语言的某些方面 比如构造函数的工作细节 在什么条件下编译器会创建内部临 时对象 或者对于效率的一般性考虑 虽然这些方面对于编写实际的应用程序非常重要 但 是不适合于一本入门级的语言书籍 在开始写作本书第三版之前 Stan Lippman 写的 Inside the C++ Object Model 参见本前言最后所附的参考文献中的 LIPPMAN96a 包含了许 多这方面的内容 当读者希望获得更详细的说明 特别是讨论基于对象和面向对象的程序设 计 时 本书常常会引用该书中的讨论 本书故意省略了 C++标准库中的某些部分 比如对本地化和算术运算库的支持 C++标 准库非常广泛 要想介绍它的所有方面 则远远超出了本书的范围 在后面所附的参考文献 中 某些书更详细地讨论了该库 见 MUSSER96 和 STROUSTRUP97 我们相信 在 这本书出版之后 一定还会有更多的关于 C++标准库各个方面的书面世 第三版的变化 vector map set 容器 以及泛型算法 本书第三版的变化主要是以下四个方面 1.涵盖了语言所增加的新特性 异常处理 运行时刻类型识别 名字空间 内置 bool 类型 新风格的类型强制转换 2.涵盖了新的 C++标准库 包括 complex 和 string 类型 auto_ptr 和 pair 类型 顺序容 器和关联容器类型 主要是 list 3.对原来的文字作了调整 以反映出标准 C++对原有语言特性的精炼 变化以及扩展 语言精炼的一个例子是 现在能够前向声明一个嵌套类型 这在以前是不允许的 语言变化 的一个例子是 一个虚拟函数的派生类实例能够返回一个 基类实例的返回类型 的派生类 这种变化支持一个被称为 clone 或 factory 的方法 关于 clone()虚拟函数 见 17.4.7 节说明 对原有语言特性进行扩展的一个例子是 现在可以显式地指定一个函数模板的一个或多个模 板实参 实际上 模板已经被大大地扩展了 差不多已经成为一个新特性 4.加强了对 C++高级特性的处理和组织方式 尤其是对于模板 类以及面向对象程序 设计 这几年 Stan 从一个相对较小的 C++提供者团体转到了一般的 C++用户团体 这种影响 使他相信 越是深入地了解问题 则程序员越是能够高明地使用 C++语言 因此 在第三版 中 许多情况下 我们已经把焦点转移到如何更好地说明底层特性的概念 以及怎样最好地 使用它们 并在适当的时候指出应该避免的潜在陷阱 C++的未来 在出版这本书的时候 ISO/ANSI++标准委员会已经完成了 C++第一个国际标准的技术 工作 该标准已于 1998 年的夏天由 ISO 公布 C++标准公布之后 支持标准 C++的 C++编译器实现出将很快会推出 随着标准的公布 C++语言的进化将会稳定下来 这种稳定性使得以标准 C++编写的复杂的程序库 可以被用 来解决工业界特有的问题 因此 在 C++世界中 我们将会看到越来越多的 C++程序库 一旦标准被公布 标准委员会仍然会继续工作 当然步伐会慢下来 以解决 C++标准 的用户所提出的解释请求 这会导致对 C++标准作一些细微的澄清和修正 如果需要 国际
分享到:
收藏