图书目录

目    录

第I部分  专业的C++简介

第1章  C++和标准库速成  3

1.1  C++速成  3

1.1.1  小程序“Hello World”  4

1.1.2  命名空间  8

1.1.3  字面量  10

1.1.4  变量  11

1.1.5  运算符  15

1.1.6  枚举  17

1.1.7  结构体  19

1.1.8  条件语句  20

1.1.9  条件运算符  22

1.1.10  逻辑比较运算符  23

1.1.11  三向比较运算符  24

1.1.12  函数  25

1.1.13  属性  27

1.1.14  C风格的数组  30

1.1.15  std::array  31

1.1.16  std::vector  32

1.1.17  std::pair  32

1.1.18  std::optional  33

1.1.19  结构化绑定  34

1.1.20  循环  34

1.1.21  初始化列表  36

1.1.22  C++中的字符串  36

1.1.23  作为面向对象语言的C++  36

1.1.24  作用域解析  40

1.1.25  统一初始化  41

1.1.26  指针和动态内存  44

1.1.27  const的用法  47

1.1.28  引用  50

1.1.29  const_cast()  58

1.1.30  异常  59

1.1.31  类型别名  60

1.1.32  类型定义  61

1.1.33  类型推断  61

1.1.34  标准库  64

1.2  第一个大型的C++程序  64

1.2.1  雇员记录系统  64

1.2.2  Employee类  64

1.2.3  Database类  68

1.2.4  用户界面  70

1.2.5  评估程序  72

1.3  本章小结  73

1.4  练习  73

第2章  使用字符串和字符串视图  74

2.1  动态字符串  74

2.1.1  C风格字符串  74

2.1.2  字符串字面量  76

2.1.3  C++ std::string类  78

2.1.4  数值转换  82

2.1.5  std::string_view类  85

2.1.6  非标准字符串  87

2.2  字符串格式化与打印  87

2.2.1  格式字符串  88

2.2.2  参数索引  89

2.2.3  打印到不同的目的地  89

2.2.4  格式字符串的编译期验证  90

2.2.5  格式说明符  91

2.2.6  格式化转义字符和字符串  94

2.2.7  格式化范围  94

2.2.8  支持自定义类型  96

2.3  本章小结  99

2.4  练习  99

第3章  编码风格  101

3.1  良好外观的重要性  101

3.1.1  事先考虑  101

3.1.2  良好风格的元素  102

3.2  为代码编写文档  102

3.2.1  使用注释的原因  102

3.2.2  注释的风格  106

3.3  分解  109

3.3.1  通过重构分解  110

3.3.2  通过设计分解  111

3.3.3  本书中的分解  111

3.4  命名  111

3.4.1  选择恰当的名称  111

3.4.2  命名约定  112

3.5  使用具有风格的语言特性  113

3.5.1  使用常量  114

3.5.2  使用引用代替指针  114

3.5.3  使用自定义异常  115

3.6  格式  115

3.6.1  关于大括号对齐的争论  115

3.6.2  关于空格和圆括号的争论  116

3.6.3  空格、制表符、换行符  117

3.7  风格的挑战  117

3.8  本章小结  117

3.9  练习  118

第II部分  专业的C++软件设计

第4章  设计专业的C++程序  123

4.1  程序设计概述  123

4.2  程序设计的重要性  124

4.3  C++设计  126

4.4  C++设计的两个原则  126

4.4.1  抽象  126

4.4.2  重用  128

4.5  重用现有代码  130

4.5.1  关于术语的说明  130

4.5.2  决定是否重用代码  130

4.5.3  重用代码的指导原则  132

4.6  设计一个国际象棋程序  137

4.6.1  需求  137

4.6.2  设计步骤  138

4.7  本章小结  143

4.8  练习  143

第5章  面向对象设计  145

5.1  过程化的思考方式  145

5.2  面向对象思想  146

5.2.1  类  146

5.2.2  组件  146

5.2.3  属性  147

5.2.4  行为  147

5.2.5  综合考虑  147

5.3  生活在类的世界里  148

5.3.1  过度使用类  148

5.3.2  过于通用的类  149

5.4  类之间的关系  150

5.4.1  “有一个”关系  150

5.4.2  “是一个”关系(继承)  150

5.4.3  “有一个”与“是一个”的区别  152

5.4.4  not-a关系  155

5.4.5  层次结构  155

5.4.6  多重继承  156

5.4.7  混入类  157

5.5  本章小结  158

5.6  练习  158

第6章  设计可重用代码  160

6.1  重用哲学  160

6.2  如何设计可重用代码  161

6.2.1  使用抽象  161

6.2.2  构建理想的重用代码  162

6.2.3  设计有用的接口  168

6.2.4  设计成功的抽象  173

6.2.5  SOLID原则  174

6.3  本章小结  174

6.4  练习  175

第III部分  C++编码方法

第7章  内存管理  179

7.1  使用动态内存  180

7.1.1  如何描绘内存  180

7.1.2  分配和释放  181

7.1.3  数组  183

7.1.4  使用指针  189

7.2  数组-指针的对偶性  190

7.2.1  数组退化为指针  190

7.2.2  并非所有指针都是数组  192

7.3  底层内存操作  192

7.3.1  指针运算  192

7.3.2  自定义内存管理  193

7.3.3  垃圾回收  194

7.3.4  对象池  194

7.4  常见的内存陷阱  194

7.4.1  数据缓冲区分配不足以及内存访问越界  194

7.4.2  内存泄漏  196

7.4.3  双重释放和无效指针  198

7.5  智能指针  199

7.5.1  unique_ptr  199

7.5.2  shared_ptr  202

7.5.3  weak_ptr  205

7.5.4  向函数传递参数  206

7.5.5  从函数中返回  206

7.5.6  enable_shared_from_this  207

7.5.7  智能指针与C风格函数的交互  207

7.5.8  过时的、移除的auto_ptr  208

7.6  本章小结  208

7.7  练习  208

第8章  熟悉类和对象  210

8.1  电子表格示例介绍  210

8.2  编写类  211

8.2.1  类定义  211

8.2.2  定义方法  213

8.2.3  使用对象  215

8.2.4  this指针  217

8.2.5  显式对象参数  218

8.3  对象的生命周期  218

8.3.1  创建对象  218

8.3.2  销毁对象  233

8.3.3  对象赋值  234

8.3.4  编译器生成的拷贝构造函数和拷贝赋值运算符  237

8.3.5  复制和赋值的区别  237

8.4  本章小结  238

8.5  练习  239

第9章  精通类和对象  240

9.1  友元  240

9.2  对象中的动态内存分配  241

9.2.1  Spreadsheet类  241

9.2.2  使用析构函数释放内存  244

9.2.3  处理复制和赋值  245

9.2.4  使用移动语义处理移动  250

9.2.5  零规则  260

9.3  与成员函数有关的更多内容  261

9.3.1  static成员函数  261

9.3.2  const成员函数  262

9.3.3  成员函数重载  263

9.3.4  内联成员函数  267

9.3.5  默认参数  268

9.4  constexpr与consteval  269

9.4.1  constexpr关键字  269

9.4.2  consteval关键字  270

9.4.3  constexpr 和 consteval 类  271

9.5  不同的数据成员类型  272

9.5.1  静态数据成员  272

9.5.2  const static数据成员  274

9.5.3  引用数据成员  274

9.6  嵌套类  276

9.7  类内的枚举类型  277

9.8  运算符重载  277

9.8.1  示例:为SpreadsheetCell实现加法  278

9.8.2  重载算术运算符  281

9.8.3  重载比较运算符  282

9.9  创建稳定的接口  286

9.10  本章小结  289

9.11  练习  290

第10章  揭秘继承技术  291

10.1  使用继承构建类  291

10.1.1  扩展类  292

10.1.2  重写成员函数  295

10.2  使用继承重用代码  302

10.2.1  WeatherPrediction类  302

10.2.2  在派生类中添加功能  303

10.2.3  在派生类中替换功能  304

10.3  利用父类  305

10.3.1  父类构造函数  305

10.3.2  父类的析构函数  306

10.3.3  构造函数和析构函数中的虚成员函数调用  307

10.3.4  使用父类成员函数  308

10.3.5  向上转型和向下转型  310

10.4  继承与多态性  311

10.4.1  回到电子表格  311

10.4.2  设计多态性的电子表格单元格  311

10.4.3  SpreadsheetCell基类  312

10.4.4  独立的派生类  313

10.4.5  利用多态性  315

10.4.6  考虑将来  316

10.4.7  提供纯虚成员函数的实现  317

10.5  多重继承  318

10.5.1  从多个类继承  318

10.5.2  名称冲突和歧义基类  319

10.6  有趣而晦涩的继承问题  321

10.6.1  修改重写成员函数的返回类型  322

10.6.2  派生类中添加虚基类成员函数的重载  324

10.6.3  继承的构造函数  325

10.6.4  重写成员函数时的特殊情况  328

10.6.5  派生类中的拷贝构造函数和赋值运算符  334

10.6.6  运行时类型工具  335

10.6.7  非public继承  337

10.6.8  虚基类  337

10.7  类型转换  340

10.7.1  static_cast()  340

10.7.2  reinterpret_cast()  341

10.7.3  dynamic_cast()  342

10.7.4  std::bit_cast()  343

10.7.5  类型转换小结  343

10.8  本章小结  344

10.9  练习  344

第11章  模块、头文件和其他主题  345

11.1  模块  345

11.1.1  非模块化代码  346

11.1.2  标准命名模块  346

11.1.3  模块接口文件  347

11.1.4  模块实现文件  348

11.1.5  从实现中分离接口  349

11.1.6  可见性和可访问性  350

11.1.7  子模块  350

11.1.8  模块划分  351

11.1.9  私有模块片段  353

11.1.10  头文件单元  355

11.1.11  可导入的标准库头文件  355

11.2  预处理指令  357

11.3  链接  358

11.3.1  内部链接  359

11.3.2  extern 关键字  360

11.4  头文件  361

11.4.1  单一定义规则(ODR)  361

11.4.2  重复定义  361

11.4.3  循环依赖  362

11.4.4  查询头文件是否存在  363

11.4.5  模块导入声明  363

11.5  核心语言特性的特性测试宏  363

11.6  static关键字  364

11.6.1  静态数据成员和成员函数  364

11.6.2  函数中的静态变量  364

11.6.3  非局部变量的初始化顺序  365

11.6.4  非局部变量的销毁顺序  365

11.7  C 风格的可变长度参数列表  365

11.7.1  访问参数  366

11.7.2  为什么不应该使用C风格的变长参数列表  367

11.8  本章小结  367

11.9  练习  367

第12章  利用模板编写泛型代码  369

12.1  模板概述  370

12.2  类模板  370

12.2.1  编写类模板  370

12.2.2  编译器处理模板的原理  378

12.2.3  将模板代码分布到多个文件中  379

12.2.4  模板参数  380

12.2.5  成员函数模板  383

12.2.6  类模板的特化  389

12.2.7  从类模板派生  391

12.2.8  继承还是特化  392

12.2.9  模板别名  392

12.3  函数模板  393

12.3.1  函数重载与函数模板  394

12.3.2  函数模板的重载  394

12.3.3  类模板的友元函数模板  395

12.3.4  对模板参数推导的更多介绍  397

12.3.5  函数模板的返回类型  397

12.3.6  简化函数模板的语法  399

12.4  变量模板  399

12.5  概念  400

12.5.1  语法  400

12.5.2  约束表达式  401

12.5.3  预定义的标准概念  403

12.5.4  类型约束的auto  404

12.5.5  类型约束和函数模板  404

12.5.6  类型约束和类模板  407

12.5.7  类型约束和类成员函数  407

12.5.8  基于约束的类模板特化和函数模板重载  408

12.5.9  最佳实践  408

12.6  本章小结  409

12.7  练习  409

第13章  C++ I/O揭秘  410

13.1  使用流  411

13.1.1  流的含义  411

13.1.2  流的来源和目的地  412

13.1.3  流式输出  412

13.1.4  流式输入  417

13.1.5  对象的输入输出  423

13.1.6  自定义的操作算子  424

13.2  字符串流  425

13.3  基于span的流  426

13.4  文件流  427

13.4.1  文本模式与二进制模式  428

13.4.2  通过seek()和tell()在文件中转移  428

13.4.3  将流链接在一起  430

13.4.4  读取整个文件  431

13.5  双向I/O  431

13.6  文件系统支持库  432

13.6.1  路径  432

13.6.2  目录条目  434

13.6.3  辅助函数  434

13.6.4  目录遍历  434

13.7  本章小结  435

13.8  练习  436

第14章  错误处理  437

14.1  错误与异常  437

14.1.1  异常的含义  438

14.1.2  C++中异常的优点  438

14.1.3  建议  439

14.2  异常机制  439

14.2.1  抛出和捕获异常  440

14.2.2  异常类型  442

14.2.3  按const引用捕获异常对象  443

14.2.4  抛出并捕获多个异常  443

14.2.5  未捕获的异常  446

14.2.6  noexcept说明符  447

14.2.7  noexcept(expression)说明符  448

14.2.8  noexcept(expression)运算符  448

14.2.9  抛出列表  448

14.3  异常与多态性  449

14.3.1  标准异常层次结构  449

14.3.2  在类层次结构中捕获异常  450

14.3.3  编写自己的异常类  451

14.3.4  嵌套异常  453

14.4  重新抛出异常  455

14.5  栈的释放与清理  456

14.5.1  使用智能指针  458

14.5.2  捕获、清理并重新抛出  458

14.6  源码位置  459

14.6.1  日志记录的源码位置  459

14.6.2  在自定义异常中自动嵌入源位置  460

14.7  堆栈跟踪  461

14.7.1  堆栈跟踪库  461

14.7.2  在自定义异常中自动嵌入堆栈跟踪  462

14.8  常见的错误处理问题  464

14.8.1  内存分配错误  464

14.8.2  构造函数中的错误  466

14.8.3  构造函数的function-try-blocks  468

14.8.4  析构函数中的错误  470

14.9  异常安全保证  471

14.10  本章小结  471

14.11  练习  471

第15章  C++运算符重载  473

15.1  运算符重载概述  473

15.1.1  重载运算符的原因  474

15.1.2  运算符重载的限制  474

15.1.3  运算符重载的选择  474

15.1.4  不应重载的运算符  476

15.1.5  可重载运算符小结  476

15.1.6  右值引用  479

15.1.7  优先级和结合性  480

15.1.8  关系运算符  481

15.1.9  替代符号  481

15.2  重载算术运算符  482

15.2.1  重载一元负号和一元正号运算符  482

15.2.2  重载递增和递减运算符  482

15.3  重载按位运算符和二元逻辑运算符  483

15.4  重载插入运算符和提取运算符  483

15.5  重载下标运算符  485

15.5.1  通过operator[]提供只读访问  488

15.5.2  多维下标运算符  489

15.5.3  非整数数组索引  490

15.5.4  静态下标运算符  490

15.6  重载函数调用运算符  491

15.7  重载解除引用运算符  492

15.7.1  实现operator*  494

15.7.2  实现operator->  494

15.7.3  operator.*和operator ->*的含义  494

15.8  编写转换运算符  495

15.8.1  auto运算符  496

15.8.2  使用显式转换运算符解决多义性问题  496

15.8.3  用于布尔表达式的转换  497

15.9  重载内存分配和内存释放运算符  498

15.9.1  new和delete的工作原理  499

15.9.2  重载operator new和operator delete  500

15.9.3  显式地删除/默认化operator new和operator delete  502

15.9.4  重载带有额外参数的operator new和operator delete  502

15.9.5  重载带有内存大小参数的operator delete  503

15.10  重载用户定义的字面量运算符  504

15.10.1  标准库定义的字面量  504

15.10.2  用户自定义的字面量  504

15.11  本章小结  506

15.12  练习  506

第16章  C++标准库概述  508

16.1  编码原则  509

16.1.1  使用模板  509

16.1.2  使用运算符重载  509

16.2  C++标准库概述  509

16.2.1  字符串  509

16.2.2  正则表达式  510

16.2.3  I/O流  510

16.2.4  智能指针  510

16.2.5  异常  510

16.2.6  标准整数类型  511

16.2.7  数学工具  511

16.2.8  整数比较  512

16.2.9  位操作  512

16.2.10  时间和日期工具  513

16.2.11  随机数  513

16.2.12  初始化列表  513

16.2.13  Pair和Tuple  513

16.2.14  词汇类型  513

16.2.15  函数对象  514

16.2.16  文件系统  514

16.2.17  多线程  514

16.2.18  类型萃取  514

16.2.19  标准库特性测试宏  514

16.2.20  <version>  515

16.2.21  源位置  516

16.2.22  堆栈跟踪  516

16.2.23  容器  516

16.2.24  算法  522

16.2.25  范围库  529

16.2.26  标准库中还缺什么  530

16.3  本章小结  530

16.4  练习  530

第17章  理解迭代器与范围库  532

17.1  迭代器  532

17.1.1  获取容器的迭代器  534

17.1.2  迭代器萃取  536

17.1.3  示例  536

17.1.4  使用迭代器特性进行函数分发  537

17.2  流迭代器  539

17.2.1  输出流迭代器:ostream_iterator  539

17.2.2  输入流迭代器:istream_iterator  540

17.2.3  输入流迭代器:istreambuf_iterator  540

17.3  迭代器适配器  540

17.3.1  插入迭代器  541

17.3.2  逆向迭代器  542

17.3.3  移动迭代器  543

17.4  范围  544

17.4.1  约束算法  545

17.4.2  视图  547

17.4.3  范围工厂  552

17.4.4  将范围转换为容器  554

17.5  本章小结  555

17.6  练习  556

第18章  标准库容器  557

18.1  容器概述  557

18.1.1  对元素的要求  558

18.1.2  异常和错误检查  559

18.2  顺序容器  559

18.2.1  vector  560

18.2.2  vector<bool>特化  578

18.2.3  deque  578

18.2.4  list  579

18.2.5  forward_list  581

18.2.6  array  584

18.3  顺序视图  585

18.3.1  span  585

18.3.2  mdspan  587

18.4  容器适配器  588

18.4.1  queue  588

18.4.2  priority_queue  591

18.4.3  stack  593

18.5  关联容器  593

18.5.1  有序关联容器  594

18.5.2  无序关联容器/哈希表  607

18.5.3  平坦集合和平坦映射关联容器适配器  613

18.5.4  关联容器的性能  614

18.6  其他容器  614

18.6.1  标准C风格数组  614

18.6.2  string  615

18.6.3  流  615

18.6.4  bitset  616

18.7  本章小结  620

18.8  练习  620

第19章  函数指针、函数对象、lambda表达式  622

19.1  函数指针  622

19.1.1  findMatches() 使用函数指针  623

19.1.2  findMatches() 函数模板  624

19.1.3  Windows DLL和函数指针  625

19.2  指向成员函数(和数据成员)的指针  626

19.3  函数对象  627

19.3.1  编写第一个函数对象  627

19.3.2  标准库中的函数对象  627

19.4  多态功能包装器  634

19.4.1  std::function  634

19.4.2  std::move_only_function  635

19.5  lambda表达式  636

19.5.1  语法  636

19.5.2  lambda表达式作为参数  640

19.5.3  泛型lambda表达式  641

19.5.4  lambda捕获表达式  641

19.5.5  模板化lambda表达式  642

19.5.6  lambda 表达式作为返回类型  643

19.5.7  未计算上下文中的lambda表达式  643

19.5.8  默认构造、拷贝和赋值  643

19.5.9  递归lambda表达式  644

19.6  调用  644

19.7  本章小结  645

19.8  练习  645

第20章  掌握标准库算法  647

20.1  算法概述  647

20.1.1  find() 和 find_if() 算法  648

20.1.2  accumulate() 算法  650

20.1.3  在算法中使用移动语义  651

20.1.4  算法回调  651

20.2  算法详解  652

20.2.1  非修改序列算法  652

20.2.2  修改序列算法  657

20.2.3  操作算法  665

20.2.4  分区算法  667

20.2.5  排序算法  668

20.2.6  二分查找算法  669

20.2.7  集合算法  670

20.2.8  最小/最大算法  672

20.2.9  并行算法  673

20.2.10  数值处理算法  674

20.2.11  约束算法  676

20.3  本章小结  678

20.4  练习  678

第21章  字符串的本地化与正则表达式  680

21.1  本地化  680

21.1.1  宽字符  680

21.1.2  非西方字符集  681

21.1.3  本地化字符串字面量  683

21.1.4  locale和facet  683

21.2  正则表达式  688

21.2.1  ECMAScript语法  689

21.2.2  regex库  693

21.2.3  regex_match()  694

21.2.4  regex_search()  696

21.2.5  regex_iterator  697

21.2.6  regex_token_iterator  698

21.2.7  regex_replace()  700

21.3  本章小结  702

21.4  练习  702

第22章  日期和时间工具  704

22.1  编译期有理数  704

22.2  持续时间  706

22.2.1  示例与duration转换  707

22.2.2  预定义的duration  709

22.2.3  标准字面量  710

22.2.4  hh_mm_ss  710

22.3  时钟  710

22.3.1  打印当前时间  711

22.3.2  执行时间  712

22.4  时间点  712

22.5  日期  714

22.5.1  创建日期  714

22.5.2  打印日期  716

22.5.3  日期运算  717

22.6  时区  717

22.7  本章小结  718

22.8  练习  719

第23章  随机数工具  720

23.1  C风格随机数生成器  720

23.2  随机数引擎  721

23.3  随机数引擎适配器  722

23.4  预定义的随机数引擎和引擎适配器  723

23.5  生成随机数  723

23.6  随机数分布  725

23.7  本章小结  728

23.8  练习  728

第24章  其他词汇类型  729

24.1  variant  729

24.2  any  731

24.3  元组  732

24.3.1  分解元组  734

24.3.2  串联  735

24.3.3  比较  736

24.3.4  make_from_tuple()  737

24.3.5  apply()  737

24.4  optional:单子式操作  737

24.5  expected  738

24.6  本章小结  741

24.7  练习  741

第IV部分  掌握C++的高级特性

第25章  自定义和扩展标准库  745

25.1  分配器  745

25.2  扩展标准库  746

25.2.1  扩展标准库的原因  747

25.2.2  编写标准库算法  747

25.2.3  编写标准库容器  749

25.3  本章小结  773

25.4  练习  774

第26章  高级模板  775

26.1  深入了解模板参数  775

26.1.1  深入了解模板类型参数  775

26.1.2  template template参数介绍  778

26.1.3  深入了解非类型模板参数  780

26.2  类模板部分特化  781

26.3  通过重载模拟函数部分特化  784

26.4  模板递归  785

26.4.1  N维网格:初次尝试  786

26.4.2  真正的N维网格  786

26.5  变参模板  788

26.5.1  类型安全的变长参数列表  788

26.5.2  可变数目的混入类  791

26.5.3  折叠表达式  792

26.6  模板元编程  794

26.6.1  编译期阶乘  794

26.6.2  循环展开  795

26.6.3  打印元组  795

26.6.4  类型萃取  798

26.6.5  模板元编程总结  809

26.7  本章小结  809

26.8  练习  809

第27章  C++多线程编程  810

27.1  多线程编程概述  811

27.1.1  争用条件  812

27.1.2  撕裂  813

27.1.3  死锁  813

27.1.4  伪共享  814

27.2  线程  815

27.2.1  通过函数指针创建线程  815

27.2.2  通过函数对象创建线程  816

27.2.3  通过lambda创建线程  817

27.2.4  通过成员函数指针创建线程  818

27.2.5  线程本地存储  818

27.2.6  取消线程  819

27.2.7  自动join线程  819

27.2.8  从线程获得结果  820

27.2.9  复制和重新抛出异常  821

27.3  原子操作库  823

27.3.1  原子操作  825

27.3.2  原子智能指针  826

27.3.3  原子引用  826

27.3.4  使用原子类型  826

27.3.5  等待原子变量  828

27.4  互斥  829

27.4.1  互斥量类  829

27.4.2  锁  831

27.4.3  std::call_once  834

27.4.4  互斥量的用法示例  835

27.5  条件变量  838

27.5.1  虚假唤醒  839

27.5.2  使用条件变量  839

27.6  latch  840

27.7  barrier  841

27.8  semaphore  843

27.9  future  843

27.9.1  std::promise和std::future  844

27.9.2  std::packaged_task  845

27.9.3  std::async  845

27.9.4  异常处理  846

27.9.5  std::shared_future  847

27.10  示例:多线程的Logger类  848

27.11  线程池  852

27.12  协程  852

27.13  线程设计和最佳实践  854

27.14  本章小结  855

27.15  练习  855

第V部分  C++软件工程

第28章  充分利用软件工程方法  859

28.1  过程的必要性  859

28.2  软件生命周期模型  860

28.2.1  瀑布模型  860

28.2.2  生鱼片模型  862

28.2.3  螺旋类模型  862

28.2.4  敏捷  864

28.3  软件工程方法论  865

28.3.1  Scrum  865

28.3.2  UP  867

28.3.3  RUP  868

28.3.4  极限编程  869

28.3.5  软件分流  872

28.4  构建自己的过程和方法  873

28.4.1  对新思想采取开放态度  873

28.4.2  提出新想法  873

28.4.3  知道什么行得通、什么行不通  873

28.4.4  不要逃避  873

28.5  版本控制  873

28.6  本章小结  875

28.7  练习  875

第29章  编写高效的C++程序  876

29.1  性能和效率概述  876

29.1.1  提升效率的两种方式  877

29.1.2  两种程序  877

29.1.3  C++是不是低效的语言  877

29.2  语言层次的效率  877

29.2.1  高效地操纵对象  878

29.2.2  预分配内存  881

29.2.3  使用内联函数  881

29.2.4  标记无法访问的代码  881

29.3  设计层次的效率  882

29.3.1  尽可能多地缓存  882

29.3.2  使用对象池  883

29.4  剖析  888

29.4.1  使用gprof的剖析示例  888

29.4.2  使用Visual C++ 2022的剖析示例  895

29.5  本章小结  897

29.6  练习  897

第30章  熟练掌握测试技术  898

30.1  质量控制  899

30.1.1  谁负责测试  899

30.1.2  bug的生命周期  899

30.1.3  bug跟踪工具  900

30.2  单元测试  901

30.2.1  单元测试方法  902

30.2.2  单元测试过程  902

30.2.3  实际中的单元测试  905

30.3  模糊测试  912

30.4  高级测试  913

30.4.1  集成测试  913

30.4.2  系统测试  914

30.4.3  回归测试  914

30.5  用于成功测试的建议  915

30.6  本章小结  915

30.7  练习  916

第31章  熟练掌握调试技术  917

31.1  调试的基本定律  917

31.2  bug分类学  918

31.3  避免bug  918

31.4  为bug做好规划  919

31.4.1  错误日志  919

31.4.2  调试跟踪  920

31.4.3  断言  927

31.4.4  崩溃转储  928

31.5  调试技术  928

31.5.1  重现bug  928

31.5.2  调试可重复的bug  929

31.5.3  调试不可重现的bug  929

31.5.4  调试退化  930

31.5.5  调试内存问题  930

31.5.6  调试多线程程序  934

31.5.7  调试示例:文章引用  934

31.5.8  从ArticleCitations示例中总结出的教训  945

31.6  本章小结  946

31.7  练习  946

第32章  使用设计技术和框架  948

32.1  容易忘记的语法  949

32.1.1  编写类  949

32.1.2  派生类  950

32.1.3  编写lambda表达式  951

32.1.4  使用“复制和交换”惯用语法  951

32.1.5  抛出和捕获异常  952

32.1.6  写入类模板  953

32.1.7  约束模板参数  953

32.1.8  写入文件  954

32.1.9  读取文件  954

32.2  始终存在更好的方法  955

32.2.1  RAII  955

32.2.2  双分派  958

32.2.3  混入类  961

32.3  面向对象的框架  965

32.3.1  使用框架  965

32.3.2  MVC范型  966

32.4  本章小结  967

32.5  练习  967

第33章  应用设计模式  968

33.1  策略模式  969

33.1.1  示例:日志机制  969

33.1.2  基于策略logger的实现  969

33.1.3 使用基于策略的Logger  970

33.2  抽象工厂模式  971

33.2.1  示例:模拟汽车工厂  971

33.2.2  实现抽象工厂  972

33.2.3  使用抽象工厂  973

33.3  工厂方法模式  974

33.3.1  示例:模拟第二个汽车工厂  974

33.3.2  实现工厂的方法  975

33.3.3  使用工厂方法  976

33.3.4  其他用法  978

33.4  其他工厂模式  978

33.5  适配器模式  979

33.5.1  示例:适配Logger类  979

33.5.2  实现适配器  980

33.5.3  使用适配器  981

33.6  代理模式  981

33.6.1  示例:隐藏网络连接问题  981

33.6.2  实现代理  981

33.6.3  使用代理  982

33.7  迭代器模式  983

33.8  观察者模式  983

33.8.1  示例:从主题中暴露事件  983

33.8.2  实现观察者  984

33.8.3  使用观察者  985

33.9  装饰器模式  986

33.9.1  示例:在网页中定义样式  986

33.9.2  装饰器的实现  987

33.9.3  使用装饰器  988

33.10  责任链模式  988

33.10.1  示例:事件处理  989

33.10.2  实现责任链  989

33.10.3  使用责任链  990

33.11  单例模式  991

33.11.1  日志记录机制  992

33.11.2  实现单例  992

33.11.3  使用单例  994

33.12  本章小结  994

33.13  练习  994

第34章  开发跨平台和跨语言的应用程序  996

34.1  跨平台开发  996

34.1.1  架构问题  997

34.1.2  实现问题  999

34.1.3  平台专用功能  1001

34.2  跨语言开发  1002

34.2.1  混用C和C++  1002

34.2.2  改变范型  1002

34.2.3  链接C代码  1005

34.2.4  从C#调用C++代码  1006

34.2.5  在C++中使用C#代码及在C#中使用C++代码  1008

34.2.6  在Java中使02用JNI调用C++代码  1009

34.2.7  从C++代码调用脚本  1011

34.2.8  从脚本调用C++代码  1011

34.2.9  从C++调用汇编代码  1013

34.3  本章小结  1014

34.4  练习  1014

——以下内容可扫封底二维码下载——

第VI部分  附录

附录A  C++面试  1019

附录B  参考文献及相关介绍  1039

附录C  标准库头文件  1048

附录D  UML简介  1054