《C++面向对象高效编程(第2版)》的所有内容都是经验之谈。书中的练习都建立在Kayshav多年的C+++经验基础上。Kayshav不仅详尽地解释了面向对象的概念以及从理论上介绍C++的语言特性,还介绍了继承、mixin类、模板类和异常这些方面的实践经验,探讨了模板实例化、共享库、线程安全性和许多其他问题。
《C++面向对象高效编程(第2版)》以帮助读者掌握C++面向对象高效编程范式为目的,详细介绍了C++编程中的各种概念和应用技巧。《C++面向对象高效编程(第2版)》共分为两部分,第一部分(第1章至第10章)介绍面向对象编程的基础和应用,如数据抽象、继承、泛型类型、异常处理等内容;第二部分(第11章至第13章)深入探讨如何建立抽象及其策略,并研究了C++对象模型。书中包含大量的代码实例,读者不仅能从理论上得以提高,而且还能轻松地在实践中应用。
《C++面向对象高效编程(第2版)》适用于C++程序员,也可供对面向对象程序设计感兴趣的编程人员及大专院校计算机专业师生参考。
目录
- 第一部分 概念、实践和应用
- 第1章 什么是面向对象编程
- 1.1 背景
- 1.1.1 面向过程编程示例
- 1.1.2 银行账户的表示
- 1.1.3 银行账户的安全
- 1.1.4 用面向对象编程解决问题
- 1.2 理解对象模型
- 1.3 术语
- 1.4 理解消息、方法和实例变量
- 1.4.1 对象中包含的内容
- 1.4.2 实例化(或创建)对象
- 1.5 什么可以作为类
- 1.6 什么不是类
- 1.7 类的目的
- 1.8 深入了解对象
- 1.8.1 对象的状态
- 1.8.2 对象状态的重要性
- 1.8.3 谁控制对象的状态
- 1.8.4 对象的行为
- 1.9 面向对象软件开发的阶段
- 1.9.1 面向对象分析(OOA)
- 1.9.2 面向对象设计(OOD)
- 1.10 面向对象编程(OOP)
- 1.11 对象模型的关键要素
- 1.12 OOP范式和语言
- 1.13 面向对象编程语言的要求
- 1.14 对象模型的优点
- 1.15 小结
- 第2章 什么是数据抽象
- 2.1 接口和实现的分离
- 2.2 对象接口的重要性
- 2.3 实现的含义
- 2.4 保护实现
- 2.5 数据封装的优点
- 2.6 接口、实现和数据封装之间的关系
- 2.7 数据封装注意事项
- 2.8 确定封装的内容
- 2.9 抽象数据类型
- 2.10 抽象数据类型——栈的实现
- 2.11 C++中的数据抽象
- 2.12 类中的访问区域
- 2.13 和类一起使用的术语
- 2.14 类的实现者
- 2.15 实现成员函数
- 2.16 识别成员函数的目标对象
- 2.17 程序示例
- 2.18 对象是重点
- 2.19 对接口的再认识
- 2.20 什么是多线程安全类
- 2.21 确保抽象的可靠性——类不变式和断言
- 2.21.1 类不变式
- 2.21.2 前置条件和后置条件
- 2.21.3 使用断言实现不变式和条件
- 2.21.4 高效使用断言
- 2.22 面向对象设计的表示法
- 2.23 Booch表示法
- 2.24 Booch中类的关系
- 2.24.1 关联
- 2.24.2 聚集(has-a)
- 2.24.3 “使用”关系
- 2.24.4 继承关系(is-a)
- 2.24.5 类范畴
- 2.25 统一建模语言(UML)
- 2.26 UML中类的关系
- 2.27 关联
- 2.27.1 作为聚集的关联
- 2.27.2 OR关联
- 2.28 组合
- 2.29 泛化关系(is-a)
- 2.30 has-a关系的重要性
- 2.31 小结
- 第3章 C++与数据抽象
- 3.1 类概念的基础
- 3.2 类要素的细节
- 3.2.1 访问区域
- 3.2.2 分析
- 3.3 复制构造函数
- 3.4 赋值操作符
- 3.5 this指针和名称重整的进一步说明
- 3.6 const成员函数的概念
- 3.7 编译器如何实现const成员函数
- 3.8 C++中类和结构的区别
- 3.9 类可以包含什么
- 3.10 设计期间的重点——类的接口
- 3.11 类名、成员函数名、参数类型和文档
- 3.12 参数传递模式——客户的角度
- 3.13 采用语义
- 3.14 为参数选择正确的模式
- 3.15 函数返回值
- 3.16 从函数中返回引用
- 3.17 编写内存安全类
- 3.18 客户对类和函数的责任
- 3.19 小结
- 第4章 OOP中的初始化和无用单元收集
- 4.1 什么是初始化
- 4.1.1 使用构造函数初始化
- 4.1.2 使用内嵌对象必须遵守的规则
- 4.2 无用单元收集问题
- 4.2.1 无用单元
- 4.2.2 悬挂引用
- 4.2.3 无用单元收集和悬挂引用的补救
- 4.2.4 无用单元收集和语言设计
- 4.2.5 在C++中何时产生无用单元
- 4.2.6 对象何时获得资源
- 4.3 C++中的无用单元收集
- 4.4 对象的标识
- 4.5 对象复制的语义
- 4.6 对象赋值的语义
- 4.7 对象相等的语义
- 4.8 为什么需要副本控制
- 4.8.1 信号量示例
- 4.8.2 许可证服务器示例
- 4.8.3 字符串类示例
- 4.9 分析
- 4.10 “写时复制”的概念
- 4.10.1 何时使用引用计数
- 4.10.2 “写时复制”小结
- 4.11 类和类型
- 4.12 小结
- 第5章 继承的概念
- 5.1 继承的基本知识
- 5.2 is-a关系的含义
- 5.3 继承关系的效果
- 5.4 多态置换原则
- 5.5 用继承扩展类层次
- 5.6 继承的一些基本优点
- 5.7 动态绑定、虚函数和多态性
- 5.7.1 动态绑定含义
- 5.7.2 动态绑定的支持——虚函数
- 5.8 继承对数据封装的影响
- 5.9 多态的含义
- 5.10 有效使用虚函数(动态绑定)
- 5.11 虚析构函数的要求
- 5.12 构造函数和虚函数
- 5.13 一般-特殊的概念
- 5.14 抽象(延期)类的概念
- 5.15 抽象类的用途
- 5.16 强大的继承
- 5.17 有效的代码复用
- 5.18 抽象基类的客户
- 5.19 继承优点小结
- 5.20 继承和动态绑定的危险
- 5.20.1 C++如何实现动态绑定(虚函数)
- 5.20.2 虚函数的开销
- 5.20.3 动态绑定和类型检查
- 5.21 不必要的继承和动态绑定
- 5.22 使用虚函数的不同模式
- 5.23 小结
- 第6章 多重继承概念
- 6.1 多重继承的简单定义
- 6.2 大学示例
- 6.3 多重继承关系的含义
- 6.4 多重继承场景
- 6.4.1 C++中解决名称冲突
- 6.4.2 二义性基类问题
- 6.5 多重继承的基本优点
- 6.6 多重继承的替换方案
- 6.6.1 第一种替换方案
- 6.6.2 第二种替换方案
- 6.7 重复继承
- 6.8 重复继承的解决方案
- 6.8.1 在C++中通过虚基类共享对象
- 6.8.2 虚基类的优点
- 6.8.3 虚基类产生的新问题
- 6.8.4 比较Eiffel和C++中的多重继承
- 6.9 继承的一般问题
- 6.10 使用mixin类加入静态功能
- 6.10.1 mixin类的定义
- 6.10.2 何时使用mixin类
- 6.11 动态变化情况的设计
- 6.11.1 角色扮演类的设计灵活性
- 6.11.2 如何使用角色扮演类
- 6.11.3 管理角色的另一种方法
- 6.11.4 TUniversityMember类对象的多态用法
- 6.11.5 按要求改动现有类
- 6.11.6 mixin类和角色对象的比较——适用范围
- 6.12 C++的私有派生
- 6.12.1 何时使用私有派生
- 6.12.2 重新导出私有基类的成员
- 6.12.3 私有派生的替换方法——包含
- 6.12.4 需要使用私有派生的情况
- 6.13 mixin类和私有派生的实用示例
- 6.14 继承与包含
- 6.15 小结
- 第7章 从类中选择性导出(友元函数)
- 7.1 需要什么
- 7.2 C++的情况
- 7.3 友元关系的含义
- 7.4 非成员函数和友元函数的应用
- 7.4.1 实例1:尽量减少类之间过多的交互
- 7.4.2 实例2:克服语法问题
- 7.4.3 实例3:需要和多个类进行通信的函数
- 7.5 非成员函数的优点
- 7.6 选择友元函数还是成员函数
- 7.7 小结
- 第8章 操作符重载的概念
- 8.1 语言类型和程序员定义类型的区别
- 8.2 什么是重载操作符
- 8.3 操作符重载的优点和缺点
- 8.3.1 更加简洁的抽象数据类型
- 8.3.2 令人费解的操作符重载
- 8.3.3 无法理解优先级和结合规则
- 8.4 C++中的重载操作符
- 8.5 ++和——操作符的另一个应用
- 8.6 更复杂的操作符——成员访问操作符:-
- 8.7 非成员函数的操作符
- 8.7.1 作为成员函数的操作符
- 8.7.2 作为非成员函数实现的操作符
- 8.7.3 为什么需要转换
- 8.8 转换函数
- 8.8.1 转换构造函数和转换函数之间的相互影响
- 8.8.2 消除对临时对象的需求
- 8.9 从操作符函数返回结果
- 8.10 赋值操作符
- 8.11 小结
- 第9章 泛型类型
- 9.1 重复性编码问题
- 9.2 智能解决方案——泛型编程
- 9.3 泛型类型(类)的基本知识
- 9.4 泛型类型和代码重复
- 9.5 泛型类实现者与客户之间的契约
- 9.5.1 这是否是良好的设计
- 9.5.2 泛型类实现中的操作符和成员函数
- 9.5.3 替换解决方案——泛型类的特殊化
- 9.6 模板特殊化
- 9.6.1 模板成员函数的特殊化
- 9.6.2 另一种替换方案:分离对象的比较
- 9.6.3 不能随意停用模板类的原因
- 9.7 模板类特殊化
- 9.8 泛型函数的概念
- 9.9 C++中模板类和成员函数的实例化
- 9.10 泛型类型和类型检查
- 9.11 约束泛型和无约束泛型
- 9.11.1 C++中对模板参数的约束
- 9.11.2 C++中模板参数的特定类型
- 9.11.3 模板参数的默认值
- 9.12 C++中对模板参数执行约束
- 9.13 泛型类和选择性导出
- 9.14 继承和泛型类
- 9.15 泛型类继承的用途
- 9.16 控制对象创建的一般技巧
- 9.17 实现计数指针
- 9.18 尽量减少模板对象的代码重复
- 9.18.1 程序的内存占用
- 9.18.2 减少模板代码的方案
- 9.19 模板类和源代码保护
- 9.20 共享(动态)库中的模板类
- 9.20.1 共享库中的模板类——多实例问题
- 9.20.2 消除共享库中的多个实例
- 9.20.3 和现有共享库链接
- 9.20.4 容器类
- 9.21 泛型类和继承的比较
- 9.22 小结
- 第10章 处理异常情况
- 10.1 处理错误状况的原因
- 10.2 错误码的替换方案
- 10.3 C++异常处理模型
- 10.3.1 C++异常机制的工作方式
- 10.3.2 try块的重要性
- 10.3.3 throw表达式的重要性
- 10.3.4 理解动态调用链
- 10.3.5 处理多个异常
- 10.3.6 catch块的责任
- 10.4 Eiffel中的异常模型
- 10.5 Eiffel和C++异常模型的优缺点
- 10.6 有效地使用C++异常
- 10.7 创建异常层次
- 10.7.1 catch处理代码的顺序
- 10.7.2 编写异常安全函数
- 10.8 项目中的异常处理架构
- 10.9 项目中错误管理的成功策略
- 10.9.1 函数不是防火墙
- 10.9.2 设计异常层次
- 10.10 异常环境中的资源管理
- 10.10.1 自动资源管理
- 10.10.2 泛化资源管理解决方案
- 10.11 异常和构造函数
- 10.11.1 从函数中返回安全资源
- 10.11.2 管理对象数组的辅助类
- 10.11.3 自动无用单元收集的开销
- 10.12 构造函数的部分完成
- 10.13 使用异常创建安全数组
- 10.14 小结
- 第二部分 构建强大的面向对象软件
- 第11章 掌握数据抽象
- 11.1 隐藏抽象的实现细节
- 11.1.1 使用句柄的优点
- 11.1.2 使用句柄的缺点
- 11.2 将指针作为数据成员使用(惰性求值)
- 11.3 控制对象创建
- 11.3.1 只允许使用new()操作符创建对象
- 11.3.2 防止使用new()操作符创建对象
- 11.4 使用指针和引用代替内嵌对象
- 11.5 避免用大型数组作为自动变量(或数据成员)
- 11.6 使用对象数组和对象指针数组
- 11.7 用对象代替基本类型指针作为数据成员和成员函数的返回值
- 11.8 与C的兼容性
- 11.9 合理选择实现:对象大小和代码效率
- 11.10 避免临时对象
- 11.11 使用复制构造函数初始化对象
- 11.12 有效使用代理对象
- 11.12.1 代理对象有助于安全共享对象
- 11.12.2 代理对象易于使用
- 11.12.3 代理对象是远程对象的替身
- 11.12.4 智能代理对象提供额外的功能
- 11.12.5 代理对象解决语法/语义的问题
- 11.12.6 泛型下标代理技术
- 11.13 使用简单的抽象建立更复杂的抽象
- 11.14 抽象必须允许客户以不同的方式使用类
- 11.15 小结
- 第12章 高效使用继承
- 12.1 用继承实现简洁的菜单和命令
- 12.2 封装创建对象的细节
- 12.3 虚构造函数的概念
- 12.4 为协议控制而组合使用虚函数和非虚函数
- 12.5 双分派概念
- 12.6 设计和实现容器类
- 12.7 设计可处理不同类型的容器
- 12.8 用泛型编程实现同质容器类
- 12.8.1 设计目的
- 12.8.2 基于模板的同质容器的优点
- 12.9 基于模板的容器的缺点
- 12.10 导航容器
- 12.11 主动迭代器
- 12.12 管理容器和迭代器——客户的角度
- 12.12.1 样式1:在容器中创建并返回迭代器供用户使用
- 12.12.2 样式2:按值返回用户可使用迭代器控制的容器
- 12.13 C++标准模板库(STL)
- 12.13.1 STL容器
- 12.13.2 迭代器
- 12.13.3 STL中的算法
- 12.14 小结
- 12.15 TArray容器的实现代码
- 第13章 理解C++对象模型
- 13.1 高效实现
- 13.2 C++表示对象的方式
- 13.2.1 没有虚函数的类
- 13.2.2 成员函数
- 13.2.3 静态数据成员
- 13.2.4 构造函数
- 13.3 包含虚函数的类
- 13.4 在共享库之间共享虚函数表
- 13.5 虚函数和多重继承(非虚基类)
- 13.6 虚基类
- 13.6.1 虚基类的成员访问
- 13.6.2 带虚函数的虚基类
- 13.7 RTTI(运行时类型识别)的实现支持
- 13.8 基于对象和面向对象编程
- 13.9 引用、指针和值
- 13.9.1 引用和指针的赋值
- 13.9.2 复制构造函数
- 13.9.3 构造函数的职责
- 13.10 复制构造函数的责任
- 13.11 优化对象的按值传递和按值返回
- 13.11.1 按值传递
- 13.11.2 按值返回
- 13.12 运行时初始化
- 13.13 小结
- 附录 A
- 参考书目和推荐读物
- 索引