首页>参考读物>计算机科学与技术>综合

C++编程思想(两卷合订本)
作者 : (美)Bruce Eckel, Chuck Allison 著
译者 : 刘宗田 袁兆山 潘秋菱 刁成嘉 等译
丛书名 : 计算机科学丛书
出版日期 : 2011-06-29
ISBN : 978-7-111-35021-7
定价 : 116.00元
扩展资源下载
扩展信息
语种 : 简体中文
页数 : 940
开本 : 16
原书名 : Thinking in C++
原出版社: Pearson Education Asia
属性分类: 店面
包含CD :
绝版 : 未绝版
图书简介

本书第1卷的第1版荣获美国《软件开发》杂志评选的1996年Jolt生产力大奖,中文版自2000年推出以来,经久不衰,获得了读者的充分肯定和高度评价。本书的第1卷是在第1版的基础上进行了更加深入的分析和修改后得到的第2版,其内容更加集中,可以供不同程度的读者选择阅读。
本书第2卷介绍了C++实用的编程技术和最佳的实践方法,深入探究了异常处理方法和异常安全设计;介绍C++的字符串、输入输出流的现代用法;解释多重继承问题的难点,描述了典型的设计模式及其实现,特别介绍了多线程处理编程技术。
本书是C++领域内一本权威的著作,书中的内容、讲授方法、练习既适合课堂教学,又适合读者自学。本书适合作为高等院校计算机及相关专业的本科生、研究生的教材,也可供从事软件开发的研究人员和科技工作者参考。

图书特色

C++编程思想(两卷合订本)
第1卷 标准C++导引(原书第2版)
第2卷 实用编程技术
Thinking in C++
Volume One: Introduction to Standard C++, Second Edition
& Volume Two: Practical Programming
(美)Bruce Eckel  Chuck Allison 著 刘宗田 袁兆山 潘秋菱 刁成嘉 等译

《C++编程思想》荣获《软件开发》杂志评选的1996年Jolt生产力大奖
本书是《C++编程思想》两卷的汇总。第1卷是在第1版的基础上进行了更加深入分析和修改后的第2版,其内容、讲授方法、选用实例以及配套的练习别具特色,可以供不同程度的读者选择阅读。第2卷介绍了C++实用的编程技术和最佳的实践方法,深入探究了异常处理方法和异常安全设计;介绍C++的字符串、输入输出流的现代用法;解释多重继承问题的难点,描述了典型的设计模式及其实现,特别介绍了多线程处理编程技术。

在本书作者的个人网站www.BruceEckel.com上提供:
本书的英文原文、源代码、练习解答指南、勘误表及补充材料。
本书相关内容的研讨和咨询。
本书第1卷及第2卷英文电子版的免费下载链接。

作者简介
Bruce Eckel 是MindView公司的总裁,向客户提供软件咨询和培训。他是C++标准委员会拥有表决权的成员之一,他也是《Java编程思想》(该书第3版影印版及翻译版已由机械工业出版社引进出版)。他曾经写过另5本面向对象编程书籍,发表过150篇以上的文章,是多本计算机杂志的专栏作家。他经常参加世界各地的研讨会并进行演讲。

Chuck Allison 曾是《C/C++ Users》杂志的资深编辑,著有《C/C++ Code Capsules》一书。他是C++标准委员会的成员,犹他谷州立学院的计算机科学教授。他还是Fresh Sources公司的总裁,该公司专门从事软件培训和教学任务。

图书前言

像任何人类语言一样,C++提供了一种表达思想的方法。如果这种表达方法是成功的,那么当问题变得更大和更复杂时,该方法将会明显地表现出比其他方法更容易和更灵活的优点。
  不能只把C++看做是语言要素的一个集合,因为有些要素单独使用是没有意义的。如果我们不只是用C++语言编写代码,而是用它思考“设计”问题,那么必须综合使用这些要素。而且,为了以这种方法理解C++,我们必须了解使用C的问题和一般的编程问题。本书讨论的是编程问题、为什么这些编程问题会成为要解决的问题以及用C++解决编程问题所采用的方法。因此,在每一章中所解释的一组语言要素,都建立在C++语言解决某一类特殊问题所用方法的基础之上。以这种方式,我希望一点一点地引导读者,从掌握C开始,直到读者使用C++变成自己的母语思维方式。
  我将始终坚持一种观点:读者应当在头脑中建立一个模型,以便从各个方面深入理解这门语言的精髓。如果读者遇到难题,他可以将问题纳入这个模型,推导出答案。我将努力把已经印在我脑海中的见解传授给读者,正是这些见解,使得我能开始“用C++进行思考”。
第1卷第2版中的新内容
  本书是第1版的彻底重写,反映了C++标准最终完成所带来的C++的所有改变,也反映了自从第1版写完后我又学习到的内容。我已经检查并重写了第1版中的全部文字,在这个过程中,我删去了一些过时的例子,修改了一些现有的例子,并增加了一些新的例子和新的练习。我对第1版的内容进行了大规模的重新整理和重新编排,以便反映新出现的更好的工具和我对人们如何学习C++的进一步理解。为方便没有C背景知识的读者能阅读本书后面的章节,在第2版增加了一章,简要地介绍C概念和基本的C++特征。
  因而,对于“第2版与第1版相比有何不同”这个问题的简要回答是:不同之处不在于版本号是新的,而是进行了重写,有的地方读者甚至无法认出原来的例子和材料。
第2卷的内容是什么
  C++标准增加了一些重要的新库,例如String、在标准C++库中的容器和算法,以及模板中的新的复杂性。这些新增的内容和其他更高级的主题被放进本书的第2卷,包括多重继承、异常处理、设计模式和建立和调试稳定系统等内容。
如何得到第2卷
  就像当前你手上的这本书一样,《C++编程思想》第2卷完全可以从我的网站www.BruceEckel.com上下载。
预备知识
  在本书第1版中,我假定读者已经学习了C,并至少具有自如阅读的水平。我的重点放在简化我认为比较困难的部分:C++语言。第2版增加了一章,快速地介绍C,并在光盘上提供“Thinking in C”的课堂讨论材料,但是即使如此,我仍然假设读者具有一定的程序设计经验。另外,正如读者可以通过读小说而直接地学会许多新词一样,读者也可以从在本书后面的文字中学习有关于C的大量知识。
学习C++
  我希望本书的读者有和我进入C++时相同的情况:作为一个C程序员,对于编程持有实在而执着的态度。但糟糕的是,我的背景和经验是在硬件层的嵌入式编程方面。在那里,C常常被看做高层语言,它对于位操作是低效率的。后来我发现,自己甚至不是一个好的C程序员,平时总是掩盖了对malloc( )和free( )、setjmp( )和longjmp( )结构以及其他“复杂”概念的无知,当开始触及这些主题时就竭力回避,而不是努力去获取新的知识。
  在我开始致力于学习C++时,当时惟一像样的书是Stroustrup夫子自道式的“专家指南”,因此我只好靠自己弄清基本概念。这引出了我的第一本关于C++的书,这本书基本上就是直接把我头脑中的经验倒出来而写成的。它的构思是作为读者的指南,引导程序员同时进入C和C++。这本书的两个版本 都收到了读者的热情反响。
  几乎就在《Using C++》出版的同时,我开始讲授这门语言。讲授C++已经变成了我的职业。自1989年以来,在授课时我看到了世界各地听众昏昏欲睡的样子、茫然不知的面容和困惑不解的表情。当我对一些人数不多的人群进行内部培训时,在练习过程中又发现了某些问题。即便那些面带微笑和会心点头的学生,实际上对许多问题也还是糊涂的。通过开创和多年主持“软件开发会议”的C++和Java系列专题,我发现,我和其他讲演者都有一种倾向,即过快地向听众灌输了过多的主题。后来,我做了一些努力,通过区别对待不同层次的听众和提供相关资料的方法,尽量吸引听众。也许这是过分的要求,但是因为我是一个抵触传统教学的人(对于大部分人而言,我相信这种抵触源于厌倦),所以希望我通过努力,使每一个人都能跟得上教学进度。
  有一段时间,我编写了大量的教学演示。这样,我结束了通过实验和重复方式进行学习(在设计C++程序的过程中,这也是一项很有用的技术)的阶段。最后,从我多年的教学经验中总结出来的所有内容,形成了一门课程。在课程中,我用一系列分离的、易于理解的步骤并采用实地课堂讨论的形式解决学习中的问题(理想的学习情况),并在每次课后面跟随着练习。
  本书的第1版是作为两学年制课程编写的,并且书中的内容已经在许多不同的课堂讨论上通过了多种形式的检验。我从每次课堂讨论上收集反馈意见,不断地修改和调整内容,直到我感觉到它已经成为一本很好的教材为止。但这本书不仅仅是课堂讨论的分发教材,而且我在其中放入了尽可能多的信息,在结构上使得它能引导读者顺利地通过当前主题和进入下一个主题。另外,这本书也适合于自学读者,能帮助他们尽快地掌握这门新的编程语言。
目标
  在这本书中,我的目标是:
  1) 以适当的进度介绍内容。每次将学习向前推进一小步,因此读者能很容易地在继续下一步学习之前消化每个已学过的概念。
  2) 尽可能使用简短的例子。当然,这有时会妨碍我解决“现实世界”的问题。但是,我发现,当初学者能够掌握例子的每个细节,而不受问题的领域所影响时,他们通常会更有兴趣进行学习。另外,在课堂情况下能达到的接受能力,对代码的长短也有严格的限制。为此,我有时会受到使用“玩具例子”的批评,但是我甘愿承受这一批评,因为这样更有利于取得某些教学法上的效果。
  3) 仔细安排描述内容的顺序,不让读者看到还没有揭示的内容。当然,这不是总能做到的;如果出现了这种情况,我将会给出简明的介绍性的描述。
  4) 只把对于理解这门语言比较重要的东西介绍给读者,而不是介绍我知道的所有内容。我相信,不同信息的重要性是不同的。有些内容是95%的程序员不需要知道的,这些东西只会迷惑人们,增加他们对该语言复杂性的感觉。举一个C语言的例子,如果我们记住运算符优先表(我是记不住的),我们就可以写更漂亮的代码。但是,如果一定要这样做,反而会使代码的读者或维护者糊涂。所以可以忘掉优先级,当不清楚时使用括号。我们对于C++中的某些内容也可以采取同样的态度,因为我认为这些内容对于写编译器的人更重要,而对于程序员就不是那么重要。
  5) 保持每一节的内容充分集中,使得授课时间以及两个练习之间的间隔时间不长。这不仅能使听众保持活跃的思想和在课堂讨论中精力集中,而且会使他们有更大的成就感。
  6) 帮助读者打下坚实的基础,使得他们能充分地理解面对的问题,从而可以顺利地转向学习更困难的课程和书籍(特别是这本书的第2卷)。
  7) 我尽力不用任何特定厂商的C++版本,因为对于学习编程语言,我不认为特定实现的细节像语言本身一样重要。大部分厂商的文档只适合于他们自己的特定实现。
各章概要
  C++是一个在已有文法上面增加了新的不同特征的语言(因此,它被认为是混合的面向对象的编程语言)。由于很多人走了学习弯路,因此我们已经开始探索C程序员转移到C++语言特征的方法。因为这是过程型训练思想的自然延伸,所以我决定去理解和重复相同的道路,并通过引出和回答一些问题来加速这一进程,这些问题是当我学习该语言时遇到的和听众在听我的课时提出来的。
  设计这门课时,我始终注意一件事:精练C++语言的学习过程。听众的反馈意见帮助我认识到哪些部分是很难学习的和需要额外解释的。在这个领域中,我曾经雄心勃勃,一次讲解包括了太多的内容。通过讲解过程,我知道了,如果包括大量新特征,就必须对它们全部作出解释,而且学生也特别容易混淆这些新特征。因此,我努力一次只介绍尽可能少的特征,理想的情况是每章一次只介绍一个主要概念。
  本书的目标是只在每一章中讲授一个概念,或只讲授一小组相关的概念,用这种方法,不会依赖于其他的特征。这样,在进入下一章的学习之前,学生可以对自己的当前知识融会贯通。为了实现这个目标,我把一些C特征留到后面的章节去介绍,甚至放在比我希望的还要往后的地方介绍。这样做的好处是读者不会因为看到了许多未解释的C++特征被使用而困惑,因此,对该语言的介绍将是和缓的,并且将反映出读者自己消化这些特征时将会采用的方式。
  下面是本书各章内容的简要说明。
  第1章  对象导言。当项目对于维护而言变得太大和太复杂时,就产生了“软件危机”。按程序员们的说法,“我们无法完成那些项目,即便能完成,它们也太昂贵了”。这引出了一些问题,在本章中我将讨论这些问题,并且讨论面向对象程序设计(OOP)的思想和如何运用这一思想解决软件危机问题。这一章引导读者了解OOP的基本概念和特征,介绍分析和设计过程。另外,在这一章中,我还将阐述采用这种语言的好处,提出关于如何转入C++语言领域的建议。
  第2章  对象的创建与使用。这一章解释用编译器和库建立程序的过程。它介绍了本书中的第一个C++程序,显示程序如何构造和编译,然后介绍标准C++中的可用对象的基本库。在结束这一章时,我们就对如何用流行的对象库编写C++程序有一个深刻的领会。
  第3章  C++中的C。这一章详细综述在C++中使用的C的特征和一些只在C++中使用的特征,还介绍在软件开发领域通用的“制作”工具,并且用它建立了本书中的所有例子(本书的源代码在www.BruceEckel.com中可找到,包含了对每章的makefile)。第3章假设读者已经具有某种过程型程序设计语言的坚实基础,例如Pascal和C语言或者甚至某种形式的Basic(只要读者已经用这种语言编写了大量的代码,特别是函数)。
  第4章  数据抽象。C++的大部分特征都围绕着创建新数据类型的能力。这不仅可以提供优质代码组织,而且可以为更强大的OOP能力奠定基础。读者将可以看到如何用将函数放入结构内部的简单过程来实现这一思想,并可以看到如何具体地完成这样的过程和创建什么样的代码。读者还能学会组织代码成为头文件和实现文件的最好方法。
  第5章  隐藏实现。通过说明结构中的一些数据和函数是private(私有的),可以把它们设置为对于这个新结构类型的用户是不可见的。这意味着能够把下层实现和客户程序员看到的接口隔离开来,这样就容易改变具体实现,而不影响客户代码。另外,C++还引入关键字class作为描述新数据类型的更具吸引力的方法,而单词“对象”的意思并不神秘,它是一种美妙的变量。
  第6章  初始化与清除。C语言的最通常的一类错误是由于变量未初始化而引起的。C++的构造函数使得程序员能保证他的新数据类型(即“他的类的对象”)的变量总是能被恰当地初始化。如果他的对象还需要某种方式的清除,他可以保证这个清除动作总是由C++的析构函数来完成。
  第7章  函数重载与默认参数。C++可以帮助程序员建立大而复杂的项目。这时,可能会引进使用相同函数名的多个库,还可能会在同一个库中选择具有不同含义的相同的名字。C++采用函数重载使这一问题容易解决。重载允许当参数表不同时重用相同的函数名。默认参数通过自动为某些参数提供默认值,使我们能用不同的方式调用同一个函数。
  第8章  常量。本章讨论了const和volatile关键字,它们在C++中有另外的含义,特别是在类的内部。我们将学习对指针定义使用const的含义。本章还说明const的含义在类的内部和外部有何不同,以及如何在类的内部创建编译时常量。
  第9章  内联函数。预处理宏省去了函数调用开销,但是也排除了有价值的C++类型检查。内联函数具有预处理宏和实际函数调用的所有好处。这一章深入地研究了内联函数的实现和使用。
  第10章  名字控制。在程序设计中,创建名字是基本的活动,而当项目变大时,名字的数目是无法限制的。C++允许在名字创建、可视性、存储代换和连接方面有大量的控制。这一章将说明如何在C++中用两种技术控制名字。第一,用关键字static控制可视性和连接,研究它对于类的特殊含义。另一种在全局范围内更有用的控制名字的技术是C++的namespace(名字空间)特征,它允许把全局名字空间划分为不同的区域。
  第11章  引用和拷贝构造函数。C++指针的作用和C指针一样,而且具有更强的C++类型检查的好处。C++还提供了另外的处理地址的方法:继Algol和Pascal之后,C++使用了“引用”,允许当程序员使用平常的符号时由编译器来处理地址操作。读者还会遇到拷贝构造函数,它通过按值传送控制将对象传送给函数或从函数中返回的方式。最后,本章还将解释C++指向成员的指针。
  第12章  运算符重载。这个特征有时被称为“语法糖(syntactic suger)”。由于运算符也可以像函数调用那样使用,这使得程序员在运用类型的语法时更加灵活。在这一章中,读者将了解到,运算符重载只是不同类型的函数调用,并且将学会如何写自己的运算符重载,学会处理参数、类型返回以及确定一个运算符是成员还是友元时的一些易混淆的情况。
  第13章  动态对象创建。一个空中交通系统将处理多少架飞机?一个CAD系统将需要多少种造形?在一般的程序设计问题中,我们不可能知道程序运行所需要的对象的数量、生命期和类型。在这一章中,我们将学习C++的new和delete如何漂亮地通过在堆上安全地创建对象而解决上述问题。我们还将看到,new和delete如何用不同的方法重载,从而使我们能控制如何分配和释放存储。
  第14章  继承和组合。数据抽象允许程序员从零开始创建新的类型。通过组合和继承,程序员可以用已存在的类型创建新的类型。用组合方法,程序员可以以老的类型作为零件组装成新的类型;而用继承方法,程序员可以创建已存在类型的一个更特殊的版本。在这一章中,读者将学习这一文法,学习如何重定义函数,以及理解构造和析构对于继承和组合的重要性。
  第15章  多态性和虚函数。单靠读者自己,可能要花九个月的时间才能发现和理解OOP的这一基石。通过一些小而简单的例子,读者可以看到如何通过继承创建一个类型族,看到在这个类型族中如何通过公共基类对这个族中的对象进行操作。关键字virtual使程序员能够按类属处理这个族中的所有对象,这意味着大块代码将不依赖于特殊类型的信息,因此,程序是可扩充的,构造程序和维护代码也变得更容易和更便宜。
  第16章  模板介绍。继承和组合允许程序员重用对象代码,但不能解决有关重用需要的所有问题。模板通过为编译器提供了一种在类或函数体中代换类型名的方法,来允许程序员重用源代码。这就支持了容器类库的使用,容器类库是使我们能快速而有效地开发面向对象程序的重要工具(标准C++库包含了一个重要的容器类库)。这一章给出了这个基本主题的详尽阐述。
  另一些主题(更高级的课题),可以在本书的第2卷中看到,本书的第2卷可以从网站www.BruceEckel.com下载。
练习
  我已经发现,在课堂讨论期间,练习对同学们的完全理解是特别有用的,因此,本书的每章后面都有一组练习。练习题的数量在第1版的基础上有很大的增加。
  在这些练习中,很多是比较简单的,可以在课堂内或实验室内用合理的时间完成,老师可以通过观察证实所有的学生正在吸收这些材料。有些练习是为了激发优秀学生的学习兴趣。大量练习被设计成能在短期内求解,目的是为了测试和完善学生所掌握的知识,而不是提出主要的挑战(也许我们将自己找到那些挑战,更可能的是,那些挑战会自动出现在我们面前)。
练习的答案
  部分练习题的答案可以在本书的电子文档“Thinking in C++ Annotated Solution Guide”中找到,只需支付很少的费用就可以从网站www.BruceEckel.com上获得这个电子文档。
源代码
  本书中的源代码是免费软件版权,通过网站www.BruceEckel.com分发。该版权防止未经允许用印刷媒体重印这些代码,但是,在许多其他情况下可以使用这些代码。
  这些代码放在一个压缩文件中,可以从任何有zip工具的平台上提取(如果没有安装合适的平台,可以从Internet上找到适合你的平台的某个版本)。
  读者可以在自己的项目中和在课堂上使用这些代码,只要遵守代码中的版权声明。
语言标准
  在本书中,当谈到遵循ISO C标准时,我一般只是说‘C’。只有当有必要区别标准C和老的、以前版本的C时,我才加以区分。
  在写这本书时,C++标准委员会完成了语言的标准化工作。这样,我将用术语“标准C++”来指代这个标准化的语言。如果我简单地谈到C++,读者就应该假设这意味着“标准C++”。
  在C++标准委员会的实际名字与标准本身的名字之间有些混淆。委员会的主席Steve Clamage就此作了如下澄清:
  有两个C++标准委员会:NCITS(以前的X3)J16委员会和ISO JTC1/SC22/WG14委员会。ANSI授权NCITS建立制订美国国家标准的技术委员会。
  1989年J16受委托制订C++美国标准。1991年WG14受委托制订国际标准。J16项目转变为“Type I”(国际)项目,并服从于ISO标准化计划。
  这两个委员会在同一时间、同一地点开会,J16的投票作为美国在WG14的票数。WG14委派J16做技术工作,并对J16的技术工作进行表决。
  最初,C++标准是作为ISO标准制订的。ANSI后来投票(在J16的建议下)决定采用ISO C++标准作为C++美国标准。
  因此,“ISO”是称呼C++标准的正确方式。
语言支持
  读者的编译器可能不支持在本书中讨论的所有特征,如果还没有编译器的最新版本就更是如此了。实现像C++这样的语言是艰巨的任务,而且读者可能希望将这些特征划分成一些部分后分别出现,而不是一下子全出现。如果读者试用本书中的某个例子,从编译器中得到了大量的错误,这可能不是代码或编译错误,而可能是他的特定编译器还没有实现例子中的某个特征。
错误
  无论一个作者具有多少发现错误的技巧,总会有一些错误漏网,它们常常能被新读者发现。如果读者发现了任何认为是错误的地方,请填写网站www.BruceEckel.com上关于本书的修改表格并在线提交,我将非常感激。

上架指导

计算机\程序设计

封底文字

本书是《C++编程思想》两卷的汇总。第1卷采用的是第2版,书中并不是按传统的方法讲解C++的概念和编程方法,而是根据作者多年在教学实践中发现的问题,用一些非常简单的例子和简练的叙述,阐明在学习C++中特别容易混淆的概念。特别是,通过示例引导读者从C++编译实现的汇编代码的角度反向审视C++的语法和语义,常常使读者有“心有灵犀一点通”的奇特效果。

第2卷介绍实用的编程技术和最佳的实践方法,解决C++开发中最困难的课题;深入研究标准C++库的功能,包括字符串、输入输出流、STL算法和容器;讲述模板的现代用法,包括模板元编程;解开对多重继承的困惑,展示RTTI的实际使用;深入探究异常处理方法,清晰解释异常安全设计;介绍多线程处理编程技术,并提供最新研究成果。


在本书作者的个人网站www.BruceEckel.com上提供:
本书的英文原文、源代码、练习解答指南、勘误表及补充材料。
本书相关内容的研讨和咨询。
本书第1卷及第2卷英文电子版的免费下载链接。

本书的附录请到华章网站(www.hzbook.com)下载。

作者简介

(美)Bruce Eckel, Chuck Allison 著:Bruce Eckel 是MindView公司的总裁,向客户提供软件咨询和培训。他是C++标准委员会拥有表决权的成员之一,他也是《Java编程思想》(该书第3版影印版及翻译版已由机械工业出版社引进出版)。他曾经写过另5本面向对象编程书籍,发表过150篇以上的文章,是多本计算机杂志的专栏作家。他经常参加世界各地的研讨会并进行演讲。 Chuck Allison 曾是《C/C++ Users》杂志的资深编辑,著有《C/C++ Code Capsules》一书。他是C++标准委员会的成员,犹他谷州立学院的计算机科学教授。他还是Fresh Sources公司的总裁,该公司专门从事软件培训和教学任务。

译者简介

刘宗田 袁兆山 潘秋菱 刁成嘉 等译:暂无简介

译者序

作为译者,我有幸组织翻译了《C++编程思想》第1版。在这之前,我仅仅耳闻这是一本别具特色的畅销书,至于如何别具特色,如何得以畅销,并不十分清楚。在第1版的翻译过程中,我逐渐领悟了Eckel编写技巧的真谛。在第1版中文版的译者序中,我曾这样总结他的技巧:“其内容、讲授方法、选用例子和跟随的练习,别具特色。原书作者不是按传统的方法讲解C++的概念和编程方法,而是根据他自己过去学习C++的亲身体会,根据他多年教学中从他的学生们的学习中发现的问题,用一些非常简单的例子和简练的叙述,阐明了在学习C++中特别容易混淆的概念。特别是,他经常通过例子引导读者从C++编译实现的汇编代码的角度反向审视C++的语法和语义,常常使读者有‘心有灵犀一点通’的奇特效果,这在以往的C++书中并不多见。”
  《C++编程思想》第1版的中文版自2000年1月第1次印刷以来,在中国市场上的畅销势头经久不衰。这充分说明了这本书在中国读者心目中的地位。
  Eckel致力于计算机程序设计语言教学数十年,而且是全心全意地从事这项工作,这本身就是难能可贵的,是他成功的根本原因。另外,他的成功还有赖于他的精益求精的精神,这不仅表现在第1版的与众不同的精心选材和认真推敲的叙述方面,也体现在第2版与第1版的不同点上。
  表面上,第2版与第1版并无太多的变化,但是通过分析,可以看出,其中的任何变化都是经过深思熟虑的。从章节上看,最大的区别是增加了两章和去掉了四章。增加的两章分别是“对象的创建与使用”和“C++中的C”。前者与“对象导言”实际上是第1版的“对象的演化”一章的彻底重写,增加了近几年面向对象方法和编程方法的最新研究与实践的丰硕成果。后者的添加不仅使不熟悉C的读者直接使用这本书成为可能,而且C本身就是C++的组成部分,这是C++得以成功的主要原因之一。删去的四章是“输入输出流介绍”、“多重继承”、“异常处理”和“运行时类型识别”。这四章属于C++中较复杂的主题,作者将它们连同C++标准完成后又增加的一些内容放到这本书的第2卷中。这样就使得这本书的第1卷内容更加集中,一般的读者可以不被这些复杂内容所困扰,而需要这些复杂知识的读者可以阅读这本书的第2卷。
  实际上,第2版的改变不仅仅在于这些章节的调整,更多的改变体现在每一章中,包括例子的调整和练习的补充。这本书更成熟了。
  受机械工业出版社华章分社计算机编辑部委托,我又承担起《C++编程思想》第2版的翻译组织任务。翻译这样的成功之作,既是机遇,更是压力。有如此众多的读者阅读我们翻译的作品,无论如何这是令人高兴的事情。诚然,吸引读者的魅力来源于原作,而不是我们的翻译技巧,但是能将如此光辉灿烂的作品变成中文版本,奉献给中国的读者,这其中毕竟融入了我们的心血,而且,第1版中文版的畅销,已经充分证明,并未因我们翻译水平的限制而黯淡了原作的光芒,这对我们已经够宽慰的了。然而,百万双眼睛在阅读这本书的同时也在审视我们的翻译水平,这就足以使我们诚惶诚恐的了。翻译在某种意义上是再创作的过程,读者见仁见智。为求更多的满意,我们只有尽力而为。由于时间和水平限制,翻译错误在所难免,恳请读者指正。
  参加第2版翻译和审校工作的人员包括:刘宗田、韩冬、蔡烈斌、袁兆山、潘秋菱、许东、李航、肖苑、刘璐、姜桂华、张卿、邵坤、陈慧琼、何允如、贾亮、童朝柱、邢大红、潘飚、刘莹、姜川、冯鸿等。
  感谢为本书第1版和第2版中文版作出贡献的所有朋友。感谢关心和支持本书翻译出版的广大读者。

刘宗田

图书目录

出版者的话
出版说明
第1卷  标准C++导引
译者序 3
前言 5
第1章  对象导言 11
1.1  抽象的过程 11
1.2  对象有一个接口 12
1.3  实现的隐藏 14
1.4  实现的重用 15
1.5  继承:重用接口 15
1.5.1  is-a 关系和is-like-a 关系 18
1.6  具有多态性的可互换对象 18
1.7  创建和销毁对象 21
1.8  异常处理:应对错误 22
1.9  分析和设计 22
1.9.1  第0阶段:制定计划 24
1.9.2  第1阶段:我们在做什么 24
1.9.3  第2阶段:我们将如何建立对象 26
1.9.4  第3阶段:创建核心 28
1.9.5  第4阶段:迭代用例 29
1.9.6  第5阶段:进化 29
1.9.7  计划的回报 30
1.10  极限编程 30
1.10.1  先写测试 31
1.10.2  结对编程 32
1.11  为什么C++会成功 32
1.11.1  一个较好的C 32
1.11.2  延续式的学习过程 33
1.11.3  效率 33
1.11.4  系统更容易表达和理解 33
1.11.5  尽量使用库 33
1.11.6  利用模板的源代码重用 34
1.11.7  错误处理 34
1.11.8  大型程序设计 34
1.12  为向OOP转变而采取的策略 34
1.12.1  指导方针 35
1.12.2  管理的障碍 35
1.13  小结 37
第2章  对象的创建与使用 38
2.1  语言的翻译过程 38
2.1.1  解释器 38
2.1.2  编译器 39
2.1.3  编译过程 39
2.2  分段编译工具 40
2.2.1  声明与定义 40
2.2.2  连接 44
2.2.3  使用库文件 44
2.3  编写第一个C++程序 45
2.3.1  使用iostream类 45
2.3.2  名字空间 46
2.3.3  程序的基本结构 47
2.3.4 “Hello, World!” 47
2.3.5  运行编译器 48
2.4  关于输入输出流 48
2.4.1  字符数组的拼接 49
2.4.2  读取输入数据 49
2.4.3  调用其他程序 50
2.5  字符串简介 50
2.6  文件的读写 51
2.7  vector简介 52
2.8  小结 55
2.9  练习 56
第3章  C++中的C 57
3.1  创建函数 57
3.1.1  函数的返回值 58
3.1.2  使用C的函数库 59
3.1.3  通过库管理器创建自己的库 59
3.2  执行控制语句 60
3.2.1  真和假 60
3.2.2  if-else语句 60
3.2.3  while语句 61
3.2.4  do-while语句 61
3.2.5  for语句 62
3.2.6  关键字break 和 continue 63
3.2.7  switch语句 64
3.2.8  使用和滥用goto 65
3.2.9  递归 65
3.3  运算符简介 66
3.3.1  优先级 66
3.3.2  自增和自减 67
3.4  数据类型简介 67
3.4.1  基本内建类型 67
3.4.2  bool类型与true和false 68
3.4.3  说明符 69
3.4.4  指针简介 70
3.4.5  修改外部对象 72
3.4.6  C++引用简介 74
3.4.7  用指针和引用作为修饰符 75
3.5  作用域 76
3.5.1  实时定义变量 77
3.6  指定存储空间分配 78
3.6.1  全局变量 78
3.6.2  局部变量 79
3.6.3  静态变量 80
3.6.4  外部变量 81
3.6.5  常量 82
3.6.6  volatile变量 83
3.7  运算符及其使用 83
3.7.1  赋值 83
3.7.2  数学运算符 83
3.7.3  关系运算符 85
3.7.4  逻辑运算符 85
3.7.5  位运算符 85
3.7.6  移位运算符 86
3.7.7  一元运算符 88
3.7.8  三元运算符 88
3.7.9  逗号运算符 89
3.7.10  使用运算符时的常见问题 89
3.7.11  转换运算符 90
3.7.12  C++的显式转换 90
3.7.13  sizeof—独立运算符 93
3.7.14  asm 关键字 94
3.7.15  显式运算符 94
3.8  创建复合类型 94
3.8.1  用typedef命名别名 95
3.8.2  用struct把变量结合在一起 95
3.8.3  用enum提高程度清晰度 97
3.8.4  用union节省内存 98
3.8.5  数组 99
3.9  调试技巧 106
3.9.1  调试标记 106
3.9.2  把变量和表达式转换成字符串 108
3.9.3  C语言assert( )宏 108
3.10  函数地址 109
3.10.1  定义函数指针 109
3.10.2  复杂的声明和定义 109
3.10.3  使用函数指针 110
3.10.4  指向函数的指针数组 111
3.11  make:管理分段编译 111
3.11.1  make的行为 112
3.11.2  本书中的makefile 114
3.11.3  makefile的一个例子 114
3.12  小结 116
3.13  练习 116
第4章  数据抽象 119
4.1  一个袖珍C库 119
4.1.1  动态存储分配 122
4.1.2  有害的猜测 124
4.2  哪儿出问题 125
4.3  基本对象 126
4.4  什么是对象 130
4.5  抽象数据类型 131
4.6  对象细节 131
4.7  头文件形式 132
4.7.1  头文件的重要性 132
4.7.2  多次声明问题 133
4.7.3  预处理器指示#define、#ifdef
和#endif 134
4.7.4  头文件的标准 134
4.7.5  头文件中的名字空间 135
4.7.6  在项目中使用头文件 135
4.8  嵌套结构 136
4.8.1  全局作用域解析 138
4.9  小结 139
4.10  练习 139
第5章  隐藏实现 142
5.1  设置限制 142
5.2  C++的访问控制 142
5.2.1  protected说明符 144
5.3  友元 144
5.3.1  嵌套友元 146
5.3.2  它是纯面向对象的吗 148
5.4  对象布局 148
5.5  类 149
5.5.1  用访问控制来修改Stash 151
5.5.2  用访问控制来修改Stack 151
5.6  句柄类 152
5.6.1  隐藏实现 152
5.6.2  减少重复编译 152
5.7  小结 154
5.8  练习 154
第6章  初始化与清除 156
6.1  用构造函数确保初始化 156
6.2  用析构函数确保清除 157
6.3  清除定义块 159
6.3.1  for循环 160
6.3.2  内存分配 161
6.4  带有构造函数和析构函数的Stash 162
6.5  带有构造函数和析构函数的Stack 164
6.6  聚合初始化 166
6.7  默认构造函数 168
6.8  小结 169
6.9  练习 169
第7章  函数重载与默认参数 171
7.1  名字修饰 172
7.1.1  用返回值重载 172
7.1.2  类型安全连接 172
7.2  重载的例子 173
7.3  联合 176
7.4  默认参数 178
7.4.1  占位符参数 179
7.5  选择重载还是默认参数 180
7.6  小结 183
7.7  练习 183
第8章  常量 185
8.1  值替代 185
8.1.1  头文件里的const 186
8.1.2  const的安全性 186
8.1.3  聚合 187
8.1.4  与C语言的区别 187
8.2  指针 188
8.2.1  指向const的指针 189
8.2.2  const指针 189
8.2.3  赋值和类型检查 190
8.3  函数参数和返回值 191
8.3.1  传递const值 191
8.3.2  返回const值 191
8.3.3  传递和返回地址 193
8.4  类 195
8.4.1  类里的const 196
8.4.2  编译期间类里的常量 198
8.4.3  const对象和成员函数 200
8.5  volatile 204
8.6  小结 205
8.7  练习 205
第9章  内联函数 207
9.1  预处理器的缺陷 207
9.1.1  宏和访问 209
9.2  内联函数 210
9.2.1  类内部的内联函数 210
9.2.2  访问函数 211
9.3  带内联函数的Stash和Stack 215
9.4  内联函数和编译器 218
9.4.1  限制 219
9.4.2  向前引用 219
9.4.3  在构造函数和析构函数里隐藏行为 220
9.5  减少混乱 220
9.6  预处理器的更多特征 221
9.6.1  标志粘贴 222
9.7  改进的错误检查 222
9.8  小结 225
9.9  练习 225
第10章  名字控制 227
10.1  来自C语言中的静态元素 227
10.1.1  函数内部的静态变量 227
10.1.2  控制连接 230
10.1.3  其他存储类型说明符 232
10.2  名字空间 232
10.2.1  创建一个名字空间 232
10.2.2  使用名字空间 234
10.2.3  名字空间的使用 237
10.3  C++中的静态成员 238
10.3.1  定义静态数据成员的存储 238
10.3.2  嵌套类和局部类 241
10.3.3  静态成员函数 242
10.4  静态初始化的相依性 244
10.4.1  怎么办 245
10.5  替代连接说明 250
10.6  小结 250
10.7  练习 251
第11章  引用和拷贝构造函数 254
11.1  C++中的指针 254
11.2  C++中的引用 254
11.2.1  函数中的引用 255
11.2.2  参数传递准则 257
11.3  拷贝构造函数 257
11.3.1  按值传递和返回 257
11.3.2  拷贝构造函数 261
11.3.3  默认拷贝构造函数 265
11.3.4  替代拷贝构造函数的方法 266
11.4  指向成员的指针 267
11.4.1  函数 269
11.5  小结 271
11.6  练习 271
第12章  运算符重载 274
12.1  两个极端 274
12.2  语法 274
12.3  可重载的运算符 275
12.3.1  一元运算符 276
12.3.2  二元运算符 279
12.3.3  参数和返回值 288
12.3.4  不常用的运算符 290
12.3.5  不能重载的运算符 295
12.4  非成员运算符 296
12.4.1  基本方针 297
12.5  重载赋值符 297
12.5.1  operator=的行为 298
12.6  自动类型转换 306
12.6.1  构造函数转换 306
12.6.2  运算符转换 307
12.6.3  类型转换例子 309
12.6.4  自动类型转换的缺陷 310
12.7  小结 312
12.8  练习 312
第13章  动态对象创建 315
13.1  对象创建 315
13.1.1  C从堆中获取存储单元的方法 316
13.1.2  operator new 317
13.1.3  operator delete 317
13.1.4  一个简单的例子 318
13.1.5  内存管理的开销 318
13.2  重新设计前面的例子 319
13.2.1  使用delete void*可能会出错 319
13.2.2  对指针的清除责任 320
13.2.3  指针的Stash 320
13.3  用于数组的new和delete 324
13.3.1  使指针更像数组 325
13.4  耗尽内存 325
13.5  重载new和delete 326
13.5.1  重载全局new和delete 327
13.5.2  对于一个类重载new和delete 328
13.5.3  为数组重载new和delete 330
13.5.4  构造函数调用 332
13.5.5  定位new和delete 333
13.6  小结 334
13.7  练习 334
第14章  继承和组合 336
14.1  组合语法 336
14.2  继承语法 337
14.3  构造函数的初始化表达式表 339
14.3.1  成员对象初始化 339
14.3.2  在初始化表达式表中的内建类型 339
14.4  组合和继承的联合 340
14.4.1  构造函数和析构函数调用的次序 341
14.5  名字隐藏 343
14.6  非自动继承的函数 346
14.6.1  继承和静态成员函数 349
14.7  组合与继承的选择 349
14.7.1 子类型设置 350
14.7.2  私有继承 352
14.8  protected 353
14.8.1  protected继承 353
14.9  运算符的重载与继承 353
14.10  多重继承 355
14.11  渐增式开发 355
14.12  向上类型转换 356
14.12.1  为什么要“向上类型转换” 357
14.12.2  向上类型转换和拷贝构造函数 357
14.12.3  组合与继承(再论) 359
14.12.4  指针和引用的向上类型转换 360
14.12.5  危机 360
14.13  小结 361
14.14  练习 361
第15章  多态性和虚函数 364
15.1  C++程序员的演变 364
15.2  向上类型转换 365
15.3  问题 366
15.3.1  函数调用捆绑 366
15.4  虚函数 366
15.4.1  扩展性 367
15.5  C++如何实现晚捆绑 369
15.5.1  存放类型信息 370
15.5.2  虚函数功能图示 371
15.5.3  撩开面纱 372
15.5.4  安装vpointer 373
15.5.5  对象是不同的 373
15.6  为什么需要虚函数 374
15.7  抽象基类和纯虚函数 375
15.7.1  纯虚定义 378
15.8  继承和VTABLE 378
15.8.1  对象切片 380
15.9  重载和重新定义 382
15.9.1  变量返回类型 383
15.10  虚函数和构造函数 385
15.10.1  构造函数调用次序 385
15.10.2  虚函数在构造函数中的行为 386
15.11  析构函数和虚拟析构函数 386
15.11.1  纯虚析构函数 388
15.11.2  析构函数中的虚机制 389
15.11.3  创建基于对象的继承 390
15.12  运算符重载 392
15.13  向下类型转换 394
15.14  小结 396
15.15  练习 397
第16章  模板介绍 400
16.1  容器 400
16.1.1  容器的需求 401
16.2  模板综述 402
16.2.1  模板方法 403
16.3  模板语法 404
16.3.1  非内联函数定义 405
16.3.2  作为模板的IntStack 406
16.3.3  模板中的常量 408
16.4  作为模板的Stash和Stack 409
16.4.1  模板化的指针Stash 411
16.5  打开和关闭所有权 415
16.6  以值存放对象 417
16.7  迭代器简介 418
16.7.1  带有迭代器的栈 425
16.7.2  带有迭代器的PStash 427
16.8  为什么使用迭代器 432
16.8.1  函数模板 434
16.9  小结 435
16.10  练习 435
附录A  编码风格
附录B  编程准则
附录C  推荐读物
第2卷  实用编程技术
译者序 441
前言 442
第一部分  建立稳定的系统
第1章  异常处理 448
1.1  传统的错误处理 448
1.2  抛出异常 450
1.3  捕获异常 451
1.3.1  try块 451
1.3.2  异常处理器 451
1.3.3  终止和恢复 452
1.4  异常匹配 453
1.4.1  捕获所有异常 454
1.4.2  重新抛出异常 454
1.4.3  不捕获异常 455
1.5  清理 456
1.5.1  资源管理 457
1.5.2  使所有事物都成为对象 458
1.5.3  auto_ptr 460
1.5.4  函数级的try块 461
1.6  标准异常 462
1.7  异常规格说明 464
1.7.1  更好的异常规格说明 467
1.7.2  异常规格说明和继承 467
1.7.3  什么时候不使用异常规格说明 468
1.8  异常安全 468
1.9  在编程中使用异常 471
1.9.1  什么时候避免异常 471
1.9.2  异常的典型应用 472
1.10  使用异常造成的开销 474
1.11  小结 476
1.12  练习 476
第2章  防御性编程 478
2.1  断言 480
2.2  一个简单的单元测试框架 482
2.2.1  自动测试 483
2.2.2  TestSuite框架 485
2.2.3  测试套件 488
2.2.4  测试框架的源代码 489
2.3  调试技术 493
2.3.1  用于代码跟踪的宏 494
2.3.2  跟踪文件 494
2.3.3  发现内存泄漏 495
2.4  小结 499
2.5  练习 500
第二部分  标准C++库
第3章  深入理解字符串 504
3.1  字符串的内部是什么 504
3.2  创建并初始化C++字符串 505
3.3  对字符串进行操作 508
3.3.1  追加、插入和连接字符串 508
3.3.2  替换字符串中的字符 509
3.3.3  使用非成员重载运算符连接 512
3.4  字符串的查找 513
3.4.1  反向查找 516
3.4.2  查找一组字符第1次或最后一次出现的位置 517
3.4.3  从字符串中删除字符 519
3.4.4  字符串的比较 520
3.4.5  字符串和字符的特性 523
3.5  字符串的应用 527
3.6  小结 531
3.7  练习 531
第4章  输入输出流 534
4.1  为什么引入输入输出流 534
4.2  救助输入输出流 537
4.2.1  插入符和提取符 537
4.2.2  通常用法 540
4.2.3  按行输入 541
4.3  处理流错误 542
4.4  文件输入输出流 544
4.4.1  一个文件处理的例子 544
4.4.2  打开模式 546
4.5  输入输出流缓冲 546
4.6  在输入输出流中定位 548
4.7  字符串输入输出流 550
4.7.1  输入字符串流 551
4.7.2  输出字符串流 552
4.8  输出流的格式化 555
4.8.1  格式化标志 555
4.8.2  格式化域 556
4.8.3  宽度、填充和精度设置 557
4.8.4  一个完整的例子 557
4.9  操纵算子 560
4.9.1  带参数的操纵算子 560
4.9.2  创建操纵算子 562
4.9.3  效用算子 563
4.10  输入输出流程序举例 565
4.10.1  维护类库的源代码 565
4.10.2  检测编译器错误 568
4.10.3  一个简单的数据记录器 570
4.11  国际化 573
4.11.1  宽字符流 574
4.11.2  区域性字符流 575
4.12  小结 577
4.13  练习 577
第5章  深入理解模板 580
5.1  模板参数 580
5.1.1  无类型模板参数 580
5.1.2  默认模板参数 582
5.1.3  模板类型的模板参数 583
5.1.4  typename关键字 587
5.1.5  以template关键字作为提示 588
5.1.6  成员模板 589
5.2  有关函数模板的几个问题 591
5.2.1  函数模板参数的类型推断 591
5.2.2  函数模板重载 594
5.2.3  以一个已生成的函数模板地址作为参数 595
5.2.4  将函数应用到STL序列容器中 598
5.2.5  函数模板的半有序 600
5.3  模板特化 601
5.3.1  显式特化 601
5.3.2  半特化 602
5.3.3  一个实例 604
5.3.4  防止模板代码膨胀 606
5.4  名称查找问题 609
5.4.1  模板中的名称 609
5.4.2  模板和友元 613
5.5  模板编程中的习语 617
5.5.1  特征 617
5.5.2  策略 621
5.5.3  奇特的递归模板模式 623
5.6  模板元编程 624
5.6.1  编译时编程 625
5.6.2  表达式模板 631
5.7  模板编译模型 636
5.7.1  包含模型 636
5.7.2  显式实例化 637
5.7.3  分离模型 638
5.8  小结 639
5.9  练习 640
第6章  通用算法 642
6.1  概述 642
6.1.1  判定函数 644
6.1.2  流迭代器 646
6.1.3  算法复杂性 647
6.2  函数对象 648
6.2.1  函数对象的分类 649
6.2.2  自动创建函数对象 649
6.2.3  可调整的函数对象 652
6.2.4  更多的函数对象例子 653
6.2.5  函数指针适配器 658
6.2.6  编写自己的函数对象适配器 662
6.3  STL算法目录 665
6.3.1  实例创建的支持工具 666
6.3.2  填充和生成 669
6.3.3  计数 670
6.3.4  操作序列 671
6.3.5  查找和替换 674
6.3.6  比较范围 679
6.3.7  删除元素 681
6.3.8  对已排序的序列进行排序和运算 684
6.3.9  堆运算 691
6.3.10  对某一范围内的所有元素进行运算 691
6.3.11  数值算法 697
6.3.12  通用实用程序 699
6.4  创建自己的STL风格算法 700
6.5  小结 701
6.6  练习 702
第7章  通用容器 706
7.1  容器和迭代器 706
7.2  概述 707
7.2.1  字符串容器 711
7.2.2  从STL容器继承 712
7.3  更多迭代器 714
7.3.1  可逆容器中的迭代器 715
7.3.2  迭代器的种类 716
7.3.3  预定义迭代器 717
7.4  基本序列容器:vector、list和deque 721
7.4.1  基本序列容器的操作 721
7.4.2  向量 723
7.4.3  双端队列 728
7.4.4  序列容器间的转换 730
7.4.5  被检查的随机访问 731
7.4.6  链表 732
7.4.7  交换序列 736
7.5  集合 737
7.6  堆栈 743
7.7  队列 745
7.8  优先队列 748
7.9  持有二进制位 755
7.9.1  bitset 756
7.9.2  vector 758
7.10  关联式容器 760
7.10.1  用于关联式容器的发生器和填充器 763
7.10.2  不可思议的映像 765
7.10.3  多重映像和重复的关键字 766
7.10.4  多重集合 768
7.11  将STL容器联合使用 771
7.12  清除容器的指针 773
7.13  创建自己的容器 774
7.14  对STL的扩充 776
7.15  非STL容器 777
7.16  小结 781
7.17  练习 781
第三部分  专   题
第8章  运行时类型识别 785
8.1  运行时类型转换 785
8.2  typeid 操作符 789
8.2.1  类型转换到中间层次类型 790
8.2.2  void型指针 791
8.2.3  运用带模板的RTTI 792
8.3  多重继承 793
8.4  合理使用RTTI 793
8.5  RTTI的机制和开销 797
8.6  小结 797
8.7  练习 798
第9章  多重继承 800
9.1  概论 800
9.2  接口继承 801
9.3  实现继承 803
9.4  重复子对象 807
9.5  虚基类 810
9.6  名字查找问题 817
9.7  避免使用多重继承 819
9.8  扩充一个接口 820
9.9  小结 823
9.10  练习 823
第10章  设计模式 825
10.1  模式的概念 825
10.2  模式分类 826
10.3  简化习语 827
10.3.1  信使 827
10.3.2  收集参数 828
10.4  单件 829
10.5  命令:选择操作 833
10.6  消除对象耦合 836
10.6.1  代理模式:作为其他对象的前端 837
10.6.2  状态模式:改变对象的行为 838
10.7  适配器模式 840
10.8  模板方法模式 841
10.9  策略模式:运行时选择算法 842
10.10  职责链模式:尝试采用一系列
策略模式 843
10.11  工厂模式:封装对象的创建 845
10.11.1  多态工厂 847
10.11.2  抽象工厂 849
10.11.3  虚构造函数 851
10.12  构建器模式:创建复杂对象 855
10.13  观察者模式 860
10.13.1  “内部类”方法 862
10.13.2  观察者模式举例 864
10.14  多重派遣 867
10.15  小结 873
10.16  练习 873
第11章  并发 875
11.1  动机 875
11.2  C++中的并发 876
11.3  定义任务 878
11.4  使用线程 879
11.4.1  创建有响应的用户界面 880
11.4.2  使用执行器简化工作 882
11.4.3  让步 884
11.4.4  休眠 885
11.4.5  优先权 886
11.5  共享有限资源 887
11.5.1  保证对象的存在 887
11.5.2  不恰当地访问资源 890
11.5.3  访问控制 892
11.5.4  使用保护简化编码 893
11.5.5  线程本地存储 896
11.6  终止任务 897
11.6.1  防止输入/输出流冲突 897
11.6.2  举例观赏植物园 898
11.6.3  阻塞时终止 901
11.6.4  中断 902
11.7  线程间协作 906
11.7.1  等待和信号 906
11.7.2  生产者-消费者关系 909
11.7.3  用队列解决线程处理的问题 912
11.7.4  广播 916
11.8  死锁 921
11.9  小结 925
11.10  练习 926
附   录
附录A  推荐读物
附录B  其他

教学资源推荐
作者: 王德才 等编著
作者: 王柯柯 主编 崔英志 黄丽丰 崔贯勋 刘恒洋 编著
作者: [美]怀亚特·S. 纽曼(Wyatt S. Newman) 著
参考读物推荐
作者: (美)Joseph J.Bambara Paul R.Allen等
作者: (美)Stephen T.Albin
作者: (美)Jason Lengstorf (英)Phil Leggetter 著