社区应用 最新帖子 精华区 社区服务 会员列表 统计排行 银行

  • 118868阅读
  • 118回复

经典名著C++ Primer中文版第三版

级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
— 本帖被 usidc5 执行加亮操作(2011-06-07) —
Stanley B Lippman 著
J o s é e L a j o i e


潘爱民 张丽 译


译序
这是我心仪已久的一本书我相信很多读者也有同样的感受
在所有的编程语言中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 译序
容易抓住C++语言的本质特征
4 与编译器无关遵从C++标准本书的内容并不特定于某一个C++编译器实现而
是适用于所有与C++标准兼容的编译器作者在讲解过程中也指出了编译器的一些内部考虑
例如编译器如何在各种上下文环境中解析重载函数如何处理除式类型转换等等这些内
容有利于加深读者对C++的理解
5 配套的练习在每一节讲解之后作者给出了一些练习这些练习反映了这一节的中
心内容读者通过这些练习可以巩固所学的知识所以本书也可以被用作教材用于系统全
面地学习C++语言
虽然本书书名C++ Primer 的中文含义是C++初级读本但是它绝对不是一本很轻
松的入门教材特别是关于名字空间函数重载解析过程模板机制和泛型算法generic
algorithms 等内容并不是一个C++初学者能够很快掌握的如果你以前没有看过其他的C++
书籍那么可能需要反复阅读多遍才能掌握本书讲述的内容如果你已经有了C++的基础比
如已经看过其他的C++入门书籍那么阅读本书可以让你快速掌握C++的要点如果你是
一名有多年C++实践经验的程序员那么阅读本书可以让你重新理解C++ 总之这是一本很
好的学习和参考书籍值得你反复阅读但是正如书名所指示的它不是一本高级书籍按
照我个人理解它的技术水准应该在中等偏深一点的层次上
本书的翻译工作由我和张丽共同完成张丽完成了初稿的翻译工作我做了第二遍翻译检
查工作书中每一句话我都认真检查过个别地方还修改了原著的一些错误C++中有些术语
还没有统一的中文说法对于这些术语的处理我们尽可能地做到符合中文的语言习惯读者
可以参考本书最后所附的英汉对照索引这份索引是由中国电力出版社的诸位编辑手工制作完
成的他们是刘江朱恩从陈维宁程璐关敏刘君夏平宋宏姚贵胜常虹乔晶
阎宏感谢他她们的辛勤劳动
在翻译过程中不断收到读者来信或者来电询问这本书的出版情况我理解读者对于一本
好书的迫切心情我的想法是有关C++的书籍和资料如此之多所以学习C++不一定非要
阅读这本书但是它可以加快你学习的步伐并且帮助你深入而全面地理解C++ 既然你已经
看到了这本书那就不要错过吧
这本书不会让你失望的我坚信这一点
潘爱民
北京大学燕北园

关键词: C++ 编程
QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 沙发  发表于: 2011-06-06

前言
本书第二版和第三版之间的变化非常大其中最值得注意的是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

QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 板凳  发表于: 2011-06-06
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++的基础是各种设施它们使用户能够通过定义新的数据类型来扩展语言本身这些


QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 地板  发表于: 2011-06-06
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 扩展
第15 章将介绍类特有的操作符重载首先给出一般的概念和设计考虑然后介绍一些
特殊的操作符如赋值下标调用以及类特有的new 和delete 操作符这一章还介绍了类
的友元它对一个类具有特殊的访问特权及其必要性然后讨论用户定义的转换包括底
层的概念和用法的扩展实例这一章还详细讨论了函数重载解析的规则并带有代码示例说

类模板是第16 章的主题类模板是用来创建类的规范描述其中的类包含一个或多个
参数化的类型或值例如一个vector 类可以对内含的元素类型进行参数化一个buffer 类
可以对内含的元素类型以及缓冲区的大小进行参数化更复杂的用法比如在分布式计算中
IPC 接口寻址接口同步接口等都可以被参数化这一章讨论了怎样定义类模板怎样
创建一个类模板特定类型的实例怎样定义类模板的成员成员函数静态成员和嵌套类型
以及怎样用类模板来组织我们的程序最后以一个扩展的类模板的例子作为结束
面向对象的程序设计和C++的支持机制是第17 18 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 库是一个用虚拟继承和多继承实现的类层次结构
本书以一个附录作为结束附录给出了每个泛型算法的简短讨论和程序例子这些算法
按字母排序以便参考
最后我们要说的是无论谁写了一本书他所省略掉的往往与他所讲述的内容一样



QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 4楼 发表于: 2011-06-06
VII 译序
重要C++语言的某些方面比如构造函数的工作细节在什么条件下编译器会创建内部临
时对象或者对于效率的一般性考虑虽然这些方面对于编写实际的应用程序非常重要但
是不适合于一本入门级的语言书籍在开始写作本书第三版之前Stan Lippman 写的Inside
the C++ Object Model 参见本前言最后所附的参考文献中的LIPPMAN96a 包含了许
多这方面的内容当读者希望获得更详细的说明特别是讨论基于对象和面向对象的程序设
计时本书常常会引用该书中的讨论
本书故意省略了C++标准库中的某些部分比如对本地化和算术运算库的支持C++标
准库非常广泛要想介绍它的所有方面则远远超出了本书的范围在后面所附的参考文献
中某些书更详细地讨论了该库见MUSSER96 和STROUSTRUP97 我们相信在
这本书出版之后一定还会有更多的关于C++标准库各个方面的书面世
第三版的变化
本书第三版的变化主要是以下四个方面
1.涵盖了语言所增加的新特性异常处理运行时刻类型识别名字空间内置bool
类型新风格的类型强制转换
2.涵盖了新的C++标准库包括complex 和string 类型auto_ptr 和pair 类型顺序容
器和关联容器类型主要是list vector map set 容器以及泛型算法
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++标准作一些细微的澄清和修正如果需要国际


VIII 译序
标准将会每五年修订一次以考虑技术的变化和工业界的需要
C++标准公布五年之后将会发生什么事情我们还不知道有可能是一个被工业界广泛
使用的新库组件将被加入到C++标准库的组件集中但是到现在为止面对C++标准委员
会已经完成的工作C++的命运就全掌握在用户的手中了
致谢
特别的感谢总是给予Bjarne Stroustrup 感谢他给予我们如此美妙的编程语言以及这
些年他对我们的关心特别感谢C++标准委员会成员的奉献和艰苦工作常常是自愿的
以及他们对C++所作的贡献
下面这些人为本书稿的各个草稿提供了许多有益的建议Paul Abrahams Michael Ball
Stephen Edwards Cay Horstmann Brian Kernighan Tom Lyons Robert Murray Ed
Scheibel Roy Turner 和Jon Wada 尤其要感谢Michael Ball 的建议和鼓励特别感谢Clovis
Tondo 和Bruce Leung 为本书所作的深刻评论
Stan 想把特别的感谢给予Shyh-Chyuan Huang 和Jinko Gotoh 感谢他们对Firebird 给与
的帮助和支持当然还有Jon Wada 和Josée
Josée 要感谢Gabby Silberman Karen Bennet 以及IBM 高级研究中心the Center for
Advanced Studies 的其他小组成员感谢他们为写作这本书所提供的支持最大的感谢要给
予Stan 感谢他带着她经历了这项伟大的冒险活动
最后我们两个都要感谢编辑们的辛苦工作以及巨大的耐心Debbie Lafferty 他从一
开始就为本书操劳Mike Hendrickson 以及John Fuller Big Purple 公司在排版上做了精彩
的工作6.1 节的插图是Elena Driskill 做的非常感谢Elena 使我们能够再版它
第二版的致谢
这本书是无数看不见的手在帮助作者的结果最由衷地感谢Barbara Moo 她的鼓励
建议以及对原手稿无数遍地仔细阅读已经无法评价特别感谢Bjarne Stroustrup 持续不断
的帮助和鼓励以及他给予我们如此美妙的编程语言还有Stephen Dewhurst 他在我第一
次学习C++时给了许多支持以及Nancy Wilkinson 另一位cfront 编写者和Gummi Bears
的提供者
Dag Brück Martin Carroll William Hopkins Brian Kernighan Andrew Koenig
Alexis Layton 以及Barbara Moo 提供了特别详细和敏锐的建议他们的评论大大完善了这本
书Andy Baily Phil Brown James Coplien Elizabeth Flanagan David Jordan Don
Kretsch Craig Rubin Jonathan Shopiro Judy Ward Nancy Wilkinson 以及Clay Wilson 检
查了书稿的各种草稿提出了许多有益的建议David Prosser 澄清了ANSI C 的许多问题
Jerry Schwarz 他实现了iostream 包提供了附录A 所依据的原始文档在第三版中变成了
第20 章非常感谢他对附录的细致检查感谢3.0 版本开发小组的其他成员Laura Eaves
George Logothetis Judy Ward 和Nancy Wilkinson
以下的人对Addison-Wesley 的手稿作了评论James Adcock Steven Bellovin Jon Forrest

IX 译序
Maurice Herlihy Norman Kerth Darrell Long Victor Milenkovic 以及Justin Smith
以下的人指出了第一版的各种印刷错误David Beckedorff Dag Bruck John Eldridge
Jim Humelsine Dave Jordan Ami Kleinman Andrew Koenig Tim O'Konski Clovis Tondo
和Steve Vinoski
我非常感谢Brian Kernighan 和Andrew Koenig 提供了大量可用的排版工具
参考文献
[BOOCH94] Booch, Grady, Object-Oriented Analysis and Design, Benjamin/Cummings,
RedwoodCity,CA (1994) ISBNO-8053-5340-2.
[GAMMA95] Gamma, Erich, Richard Helm, Ralph Johnson, and John Vlissides, Design
Patterns, Addison Wesley Longman, Inc., Reading, MA (1995) ISBN 0- 201-63361-2.
[GHEZZI97] Ghezzi, Carlo, and Mehdi Jazayeri, Programming Language Concepts, 3rd
Edition, John Wiley and Sons, New York, NY (1997) ISBN 0-471-10426-4.
[HARBISON88] Samuel P. Harbison and Guy L. Steele, Jr, C: A Reference Manual, 3rd
Edition, Prentice-Hall, Englewood Cliffs, NJ (l988) ISBN 0-13-110933-2.
[ISO-C++97] Draft Proposed International Standard for Information Systems —
Programming Language C++ - Final Draft (FDIS) 14882.
[KERNIGHAN88] Kernighan, Brian W., and Dennis M. Ritchie, The C Programming
Language, Prentice-Hall, Englewood Cliffs, NJ (1988) ISBN 0-13-110362-8.
[KOENIG97] Koenig, Andrew, and Barbara Moo, Ruminations on C++, Addison Wesley
Longman, Inc., Reading, MA (1997) lSBN 0-201-42339-l.
[LIPPMAN91] Lippman, Stanley, C++ Primer, 2nd Edition, Addison Wesley Longman,
Inc., Reading, MA (1991) ISBN 0-201-54848-8.
[LIPPMAN96a] Lippman, Stanley, Inside the C++ Object Model, Addison Wesley
Longman, Inc., Reading, MA (1996) ISBN 0-201-83454-5.
[LIPPMAN96b] Lippman, Stanley, Editor, C++ Gems, a SIGS Books imprint, Cambridge
University Press, Cambridge,England (1996) ISBN0-13570581-9.
[MEYERS98] Meyers, Scott, Effective C++, 2nd Edition, Addison Wesley Longman, Inc.,
Reading, MA (1998) ISBN 0-201-92488-9.
[MEYERS96] Meyers, Scott, More Effective C++, Addison Wesley Longman, Inc., Reading,
MA (1996) ISBN 0-201-63371-X.
[MURRAY93] Murray, Robert B., C++ Strategies and Tactics, Addison Wesley Longman,
Inc., Reading, MA (1993) ISBN 0-20l-56382-7.
[MUSSER96J Musser, David R., and Atul Saini, STL Tutorial and Reference Guide, Addison
Wesley Longman, Inc., Reading, MA (1996) ISBN 0-201-63398-l.

QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 5楼 发表于: 2011-06-06
第一篇
C++概述
我们编写的程序由两个主要方面组成
1 算法的集合就是将指令组织成程序来解决某个特定的问题
2 数据的集合算法在这些数据上操作以提供问题的解决方案
纵观短暂的计算机发展史这两个主要方面算法和数据一直保持不变发展演化的
是它们之间的关系就是所谓的程序设计方法programming paradigm
在过程化程序设计方法procedural programming 中一个问题可直接由一组算法来建
立模型例如公共图书馆的资料借阅/登记check out/check in 系统是由一系列过程表现
出来的其中两个主要的过程是资料的借阅和登记这些数据被独立存储起来我们既可以
在某个全局位置上访问这些数据或者把数据传递给过程以便它能够访问这些数据Fortran
C 和 Pascal 是三种著名的过程语言C++也支持过程化程序设计单独的过程如check_in()
check_out() over_due() fine()等等都被称为函数第三篇将集中讨论C++对过程化程序
设计方法的支持尤其将重点讨论函数函数模板和通用算法
在20 世纪70 年代程序设计的焦点从过程化程序设计方法转移到了抽象数据类型
abstract data type 简写为ADT 的程序设计上现在通常称之为基于对象(object based
的程序设计在基于对象的程序设计方法中我们通过一组数据抽象来建立问题的模型在
C++中我们把这些抽象称为类class 例如在这种方法下图书馆资料借阅登记系统就
由类的对象实例比如书借阅者还书时间罚款等之间的相互作用表现出来以此表
示出图书馆的抽象概念与每个类相关的算法被称为该类的公有接口public interface 数
据以私有形式被存储在每个对象中对数据的访问应与一般的程序代码隔离开来CLU Ada
和Modula-2 是三种支持抽象数据类型的程序设计语言第四篇将说明和讨论C++对抽象数据
类型程序设计方法的支持
面向对象的程序设计方法通过继承inheritance 机制和动态绑定dynamic binding 机
制扩展了抽象数据类型继承机制是对现有实现代码的重用动态绑定是指对现有的公有接
口的重用以前独立的类型现在有了类型/子类型的特定关系一本书一盒录像带一段录
音甚至孩子的宠物尽管它们有各自的借阅/登记方式但都可以成为图书馆的收藏资料
共享的公有接口和私有的数据都放在一个抽象类图书馆资料LibraryMaterial 中每个特
殊的图书馆资料类都从LibraryMaterial 抽象类继承共享的行为它们只需要提供与自身行为相
关的算法和数据Simula Smalltalk 和Java 是三种支持面向对象程序设计方法的著名语言
第五篇将集中讨论C++对面向对象程序设计方法的支持
C++是一种支持多种程序设计方法的语言虽然我们主要把它当作面向对象的语言但
实际上它也提供对过程化的和基于对象的程序设计方法的支持这样做的好处是对每个问题
都能够提供最合适的解决方案事实上没有一种程序设计方法能够对所有的问题都提供最
好的解决方案这样做带来的缺点是使得语言过于庞大复杂


2 第一篇 C++概述
第一篇将对整个C++进行快速浏览这样做的一个原因是它可以提供对语言特性的介
绍以便我们在完全面对这些特性之前可以自由地引用语言的各个部分例如直到第13
章我们才会详细介绍类但如果到那时候才提起类那么在此之前我们将不得不使用很多非
典型的不恰当的程序例子
提供快速浏览的第二个原因是从美学的角度出发除非首先让你领略到贝多芬交响曲的
美丽与博大否则无关联的升半音降半音八度音符和弦等一定会让你厌烦但
是只有掌握了这些细节才有可能创作音乐程序设计也一样精通C++程序设计的基础
是首先要穿过操作符优先级或标准算术转换规则的迷宫这样做既是必要的也是非常枯燥

第1 章将首先介绍C++语言的基本元素包括内置数据类型变量表达式语句函
数它将通过一个最小的并且是合法的C++程序来讨论程序的编译过程预处理以及
C++对输入输出的支持这一章将给出多个简单但完整的C++程序鼓励读者亲自编译并执
行这些程序
第2 章我们将浏览一个过程化程序一个基于对象的程序和一个面向对象的程序它们
都实现了一个数组一个由相同类型的元素组成的有限元素的集合然后我们将这些程
序中的数组抽象与C++标准库中的向量vector 类进行比较同时也将首次介绍标准库中
的通用算法沿着这条路线我们还将介绍C++对异常处理模板名字空间的支持实际
上这一章对整个C++语言作了大致的介绍细节部分将在以后各章节中详细介绍
部分读者可能会感觉第2 章很难理解给出的许多资料没有初学者所期望的完整说明这
些细节在以后的章节中讨论如果你对某些细节部分感到吃力或失去耐心建议略读或跳
过它们等到熟悉这些资料以后再回头重读这些内容第3 章将以传统的叙述方式进行
建议对第2 章不够适应的读者从第3 章开始





QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 6楼 发表于: 2011-06-06
1
开 始
本章介绍C++语言的基本元素包括内置数据类型对象的定义表达式语句
函数的定义和使用本章将给出一个最小的合法C++程序主要用它来讨论程序的
编译过程预处理并将首次介绍C++对输入输出的支持我们还将给出一些简
单但完整的C++程序
1.1 问题的解决
程序常常是针对某些要解决的问题和任务而编写的我们来看一个例子某个书店将每
本售出图书的书名和出版社输入到一个文件中这些信息以书售出的时间顺序输入每两
周店主将手工计算每本书的销售量以及每个出版社的销售量报表以出版社名称的字母顺
序排列以使下订单现在我们希望写一个程序来完成这项工作
解决大问题的一种方法是把它分解成许多小问题理想情况下这些小问题可以很容
易地被解决然后再把它们合在一起就可以解决大问题了如果新分割的小问题解决起
来还是太大就把它分割得再小一些重复整个过程直到能够解决每个小问题这个策略
就是分而治之divide and conquer 和逐步求精stepwise refinement 书店问题可以分解
成四个子问题或任务
1 读销售文件
2 根据书名和出版社计算销售量
3 以出版社名称对书名进行排序
4 输出结果
我们知道怎样解决第1 2 和4 个子问题因此它们不需要进一步分解但是第3 个子
问题解决起来还是有些大所以对这个子问题重复我们的做法继续分解
3a 按出版社排序
3b 对每个出版社的书按书名排序
3c 在每个出版社的组中比较相邻的书名如果两者匹配增加第一个的数量删除
第二个
3a 3b 和3c 所代表的问题现在都已经能够解决了由于我们能够解决这些子问题




4 第一章 开始
因此也就能够有效地解决原始的大问题了而且我们也知道任务的原始顺序是不正确的
正确的动作序列应该是
l 读销售文件
2 对文件排序——先按出版社然后在出版社内部按书名排序
3 压缩重复的书名
4 将结果写入文件
这个动作序列就是算法algorithm 下一步我们把算法转换成一种特定的程序设计语
言——在这里是C++语言
1.2 C++程序
在C++中动作被称为表达式expression 以分号结尾的表达式被称作语句statement
C++中最小的程序单元是语句在自然语言中与此类似的结构就是句子例如下面是一
组C++语句
int book_count = 0;
book_count = books_on_shelf + books_on_order;
cout << "The value of book_count: " << book_count;
第一条语句是一个声明declaration 语句book_count 被称为标识符identifier 或符
号变量symbolic variable 简称变量或者对象object 它定义了计算机内存的一块
区域并且与名字book_count 相关联被用来存储整数值0 是一个文字常量literal constant
book_count 被初始化为0
第二条语句是一个赋值assignment 语句它把 books_on_shelf 和 books_on_order
的值
相加并把结果放入与book_count 相关联的计算机内存区域中这里假定books_on_shelf 和
books_on_order 已经在前面的代码中被声明为整型并赋了初值
第三条是输出output 语句cout 是与用户终端相关联的输出目标<<是输出操作符
该语句向cout 即用户终端先输出用引号括起来的字符串文字然后输出存储在与名字
books_count 相关联的内存区域中的值假设此时books_count 中的值为11273 那么输出结
果为
the value of book_count: 11273
把语句按逻辑语义分组就形成了一些有名字的单元这些单元被称为函数function
例如把所有需要读取销售文件的语句组织到一个被称为readln()的函数中类似地我们
可以构成sort() compact()和print()函数
在C++中每个程序必须包含一个被称作main()的函数它是由程序员提供的并且只
有这样的程序才能运行下面是按前述算法定义的一种main()函数
int main()
{
readIn();
sort();
compact();

5 第一章 开始
print();
return 0;
}
C++程序从main()函数的第一条语句开始执行在本例中程序从函数readln()开始并
且程序按顺序执行main()函数中的语句在执行完main()函数的最后一条语句之后程序
正常结束
函数由四部分组成返回类型函数名参数表以及函数体前三部分合起来称为函
数原型function prototype
参数表由小括号括起来包含一个或多个由逗号分开的参数函数体由一对花括号括起
来由程序语句序列构成
在本例中main()函数的函数体调用invoke 函数 readIn() sort() compact()和 print().
当这些函数调用都完成时下面的语句
return 0
将被执行return 是C++预定义的语句它提供了终止函数执行的一种方法当return 语句
提供了一个值时例如0 这个值就成为函数的返回值return value 本例中返回值为0
表示main()函数成功执行完毕标准C++中如果main()函数没有显式地提供返回语句则
它缺省返回0
现在我们来看一下如果想让我们的程序能够执行起来我们还需要做哪些准备工作
首先必须提供函数readln() sort() compact()以及print()的定义下面的哑函数实例已经
足够满足这个要求了
void readIn() { cout << "readIn()\n"; }
void sort() { cout << "sort()\n"; }
void compact() { cout << "compact()\n"; }
void print() { cout << "print()\n"; }
void 用来指定一个没有返回值的函数正如上面的定义所示每个函数在被main()函数
调用时只会简单地在用户终端上显示它的存在以后我们会用真正的实现函数来代替这些
哑函数
这种渐进式生成程序的方法为控制程序设计中不可避免的错误提供了一种有效的控
制手段试图一下子就能写出一个完全成功的程序几乎是不可能的
程序源文件的名字一般包括两部分文件名例如bookstore 以及文件后缀文件后
缀一般用来标识文件的内容比如文件
bookstore.h
在C 或C++中习惯上被称为头header 文件标准C++头文件没有后缀这是个例
外而以下文件
bookstore.c
习惯上被当作C 程序文本文件但在UNIX 操作系统中以下文件
bookstore.c
习惯上被当作C++程序的文本文件C++程序文件的后缀在不同的C++实现产品中是不



6 第一章 开始
同的特别在DOS 中大写的字母C 与小写的字母c 是不能区分的其他常用来识别C++程
序文本文件的后缀还包括
bookstore.cxx
bookstore.cpp
类似地头文件的后缀在C++的不同实现中也不相同这也是标准C++没有指定头文件
后缀的一个原因请查阅你的编译器的用户指南以确定在当前平台上使用什么后缀
使用某个文本编辑器将下面这段完整的程序输入到一个C++文本文件中
#include <iostream>
using namespace std;
void read() { cout << "read()\n"; }
void sort() { cout << "sort()\n"; }
void compact() { cout << "compact()\n"; }
void write() { cout << "write()\n"; }
int main()
{
read();
sort();
compact();
write();
return 0;
}
iostream是输入输出流库标准文件注意它没有后缀它包含cout 的信息这对我们
的程序是必需的#include 是预处理器指示符preprocessor directive 它把iostream 的内

读入我们的文本文件中1.3 节将讨论预处理器指示符
在C++标准库中定义的名字如cout 不能在程序中直接使用除非在预处理器指示符
#include <iostream>
后面加上语句
using namespace std;
这条语句被称作using 指示符using directive C++标准库中的名字都是在一个称作
std 的名字空间中声明的这些名字在我们的程序文本文件中是不可见的除非我们显式地使
它们可见using 指示符告诉编译器要使用在名字空间std 中声明的名字在2.7 和2.8 节
中将更进一步讨论名字空间与using 指示符1
程序已经被输入到文件如prog1.c 中之后接下来就应将其编译在Unix 系统中
按以下步骤进行$表示系统提示符
$ CC prog1.C
用来调用C++编译器的命令的名字在不同的实现中也不相同在Windows 中通常通
1在本书写作时大约指1997 年前后——译注并不是所有的C++实现都支持名字空间如果你使用的C++
实现不支持名字空间那么using 指示符必须要忽略掉因为本书的许多例子都是用不支持名字空间的C++
实现来编译的所以绝大多数的代码例子都省略了using 指示符

QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 7楼 发表于: 2011-06-06
过选择菜单项来调用命令CC 是Unix 工作站上使用 C++编译器的命令名可以通过参考
手册或系统管理员获得系统的C++命令名
编译器的一部分工作是分析程序代码的正确性编译器不能判断程序的语义是否正确
但能够判断出程序形式form 上的错误下面是两个常见的程序形式错误
1 语法错误程序员犯了C++语言的语法错误例如
int main ( { // 错误缺少
readIn(): // 错误非法字符
sort();
compact();
print();
return 0 // 错误缺少 ';'
}
2 类型错误在C++中每个数据项都有一个相对应的数据类型例如10 是一个整
型数值由双引号括起来的词hello 是一个字符串如果为一个需要整型参数的函数提供
了一个字符串编译器就会报告类型错误
错误消息包含一个行号以及编译器对错误的简要描述按报告的顺序逐一修正错误是
个好的习惯一个简单的错误常常有很多关联影响会使编译器报告的错误比实际要多得多
因此一旦错误被改正后应当马上重新编译这个循环过程通常被称为编辑一编译一调试
edit compile debug
编译器的第二部分工作是转换正确的程序代码这种转换被称为代码生成code
generation 典型情况下它生成目标代码或汇编指令代码这些代码能够被运行该程序的
计算机所理解
成功编译的结果是一个可执行文件前面的程序执行时其输出结果如下
readln()
sort()
compact()
print()
C++定义了一组内置的基本数据类型整数类型int 浮点数类型float 字符类
型char 以及只有false 和true 两个值的布尔类型boolean 每种类型都与C++语言中
某一个关键字keyword 相关联程序中的每个对象都与一个特定的类型相关联例如下
面的代码
int age = 10;
double price = 19.99;
char delimiter = ' ';
bool found = false;
定义了四个对象age price delimiter 和found 分别是整数类型双精度浮点数类型
字符类型和布尔类型每个类型都赋予了一个文字常量初始值整数10 浮点数19.99 空
格字符布尔值false
在内置类型之间经常发生隐式的类型转换Conversion 例如将一个double 双精度
型的常量赋给一个int 型的age




age = 33.333;
实际上赋给age 的是被截断后的整数值33 [标准转换standard conversion 以及一
般类型的转换将在4.14 节中详细讨论]
C++标准库还提供了一组扩展的基本数据类型其中包括字符串string 复数complex
number 向量vector 和列表list 例如
// 为了使用string 对象下面的头文件是必需的
#include <string>
string current_chapter = "Getting Started";
// 为了使用vector 对象下面的头文件是必需的
#include <vector>
vector<string> chapter_titles( 20);
current_chapter 是一个字符串对象被初始化为字符串文字Getting Started chapter_title
是一个向量包含有20 个字符串类型的元素以下这种特殊语法
vector <string>
指示编译器创建一个能够存放字符串元素的向量类型要定义一个能够存放20 个整数的
向量对象我们可以这样写
vector<int> ivec(20);
本书对向量还将进行更多的描述
无论是一种语言还是它的标准库都不可能提供实际程序设计环境要求的所有数据类型
因此现代语言都提供了类型定义工具设施使我们能够在语言中引入新的类型这些类型
的用法与内置类型的用法一样方便在C++中这种设施就是类机制在C++中像string
complex vector list 这样的标准库类型都被设计成类实际上输入输出库也是这样的
类设施可能是C++中最重要的组成部分第2 章对整个类机制作了基本的概述性介绍
1.2.1 程序流程控制
缺省情况下语句将按顺序执行例如在前面的程序中重新列在下面read()总
是先被执行然后是sort() compact() write()
int main()
{
read();
sort();
compact();
write();
return 0;
}
然而如果销售进展得很慢例如只有0 或1 项那么就没有必要排序和压缩了但
是我们仍然需要输出这一项销售记录或者指出没有销售记录产生通过条件语句if 我们可
以完成这项工作假设已经重写了readln()函数使其能够返回读入的项数
// read()返回读入的项数





// 返回值的类型为int
int read() { ... }
// ...
int main()
{
int count = read();
// 如果读入的项数大于1
// 就调用sort()和compact()
if ( count > 1 ) {
sort();
compact();
}
if ( count == 0 )
cout << "no sales for this month\n";
else write();
return 0;
}
第一个if 语句给出了在括号中的条件表达式为真的情况下应该执行的动作在这个被修
改过的程序中只有在count 大于1 的时候sort() compact()函数才会被调用在第一个if
语句中为两个执行分支如果条件为真在这里即如果count 等于0 则简单地输出没行
销售产量否则只要count 不等于0 就调用write() 我们将在5. 3 节中详细讨论if 语句
第二种非顺序执行的语句是迭代iterate 或称循环loop 语句当条件保持为真的时
候循环重复执行一条或多条语句例如
int main()
{
int iterations = 0;
bool continue_loop = true;
while ( continue_loop != false )
{
iterations++;
cout << "the while loop has executed "
<< iterations << " times\n";
if ( iterations == 5 )
continue_loop = false;
}
return 0;
}
在这个看似人为构造的例子中while 循环执行5 次再到iterations 等于5 并且
continue_loop 被赋值为false 如下语句
iterations++;

QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 8楼 发表于: 2011-06-06
将使iterations 加1 在1.5 节中将有更实际的while 循环的例子第15 章将详细讲解循
环语句
1.3 预处理器指示符
头文件通过include 预处理器指示符preprocessor include directive 而成为我们程序的
一部分预处理器指示符用# 号标识这个符号将放在程序中该行的最起始一列上处理
这些指示符的程序被称做预处理器preprocessor 通常捆绑在编译器中
#include 指示符读入指定文件的内容它有两种格式
#include <some_file.h>
#include "my_file.h"
如果文件名用尖括号< 和> 括起来表明这个文件是一个工程或标准头文件查
找过程会检查预定义的目录我们可以通过设置搜索路径环境变量或命令行选项来修改这些
目录在不同的平台上这些方法大不相同建议你请教同事或查阅编译器手册以获得更进
一步的信息如果文件名用一对引号括起来则表明该文件是用户提供的头文件查找该
文件时将从当前文件目录开始
被包含的文件还可以含有#include 指示符由于嵌套包含文件的原因一个头文件可能
会被多次包含在一个源文件中条件指示符可防止这种头文件的重复处理例如
#ifndef BOOKSTORE_H
#define BOOKSTORE_H
/* Bookstore.h 的内容 */
#endif
条件指示符#ifndef 检查BOOKSTORE_H 在前面是否已经被定义这里BOOKSTORE_H
是一个预编译器常量习惯上预编译器常量往往被写成大写字母如果BOOKSTORE_H
在前面没有被定义则条件指示符的值为真于是从#ifndef 到#endif 之间的所有语句都被包
含进来进行处理相反如果#ifndef 指示符的值为假则它与#endif 指示符之间的行将被忽

为了保证头文件只被处理一次把如下#define 指示符
#define BOOKSTORE_H
放在#ifndef 后面这样在头文件的内容第一次被处理时BOOKSTORE_H 将被定义
从而防止了在程序文本文件中以后#ifndef 指示符的值为真
只要不存在两个必须包含的头文件要检查一个同名的预处理器常量这样的情形这
个策略就能够很好地运作
#ifdef 指示符常被用来判断一个预处理器常量是否已被定义以便有条件地包含程序代
码例如
int main()
{
#ifdef DEBUG
cout << "Beginning execution of main()\n";
#endif




string word;
vector< string > text;
while ( cin >> word )
{
#ifdef DEBUG
cout << "word read: " << word << "\n";
#endif
text.push_back( word );
}
// ...
}
本例中如果没有定义DEBUG 实际被编译的程序代码如下
int main()
{
string word;
vector< string > text;
while ( cin >> word )
{
text.push_back( word );
}
// ...
}
反之如果定义了DEBUG 则传给编译器的程序代码是
int main()
{
cout << "Beginning execution of main()\n";
string word;
vector< string > text;
while ( cin >> word )
{
cout << "word read: " << word << "\n";
text.push_back( word );
}
// ...
}
我们在编译程序时可以使用-D 选项并且在后面写上预处理器常量的名字这样就能在
命令行中定义预处理器常量2
$ CC -DDEBUG main.C
也可以在程序中用#define 指示符定义预处理器常量
2对于UNIX 系统确实是这样的Windows 程序员应该检查一下编译器的用户指南



编译C++程序时编译器自动定义了一个预处理器名字__cplusplus 注意前面有两个下
划线因此我们可以根据它来判断该程序是否是C++程序以便有条件地包含一些代码
例如
#ifdef __cplusplus
// 不错我们要编译C++
// extern "C" 到第7 章再解释
extern "C"
#endif
int min( int, int );
在编译标准C 时编译器将自动定义名字__STDC__ 当然__cplusplus 与__STDC__
不会同时被定义
另外两个比较有用的预定义名字是__LINE__和__FILE__ __LINE__记录文件已经被
编译的行数__FILE__包含正在被编译的文件的名字可以这样使用它们
if ( element_count == 0 )
cerr << "Error: " << __FILE__
<< " : line " << __LINE__
<< "element_count must be non-zero.\n";
另外两个预定义名字分别包含当前被编译文件的编译时间__TIME__ 和日期
__DATE__ 时间格式为hh:mm:ss 因此如果在上午8 点17 分编译一个文件则时间表
示为08:17:05 如果这一天是1996 年10 月31 日星期四则日期表示为
Oct 31 1996
若当前处理的行或文件发生变化则__LINE__和__FILE__的值将分别被改变其他四个
预定义名字在编译期间保持不变它们的值也不能被修改
assert()是C 语台标准库中提供的一个通用预处理器宏在代码中常利用assert()来判断一
个必需的前提条件以便程序能够正确执行例如假定我们要读入一个文本文件并对其
中的词进行排序必需的前提条件是文件名已经提供给我们了这样我们才能打开这个文件
为了使用assert() 必须包含与之相关联的头文件
#include <assert.h>
下面是一个简单的使用示例
assert( filename != 0 );
assert()将测试filename 不等于0 的条件是否满足这表示为了后面的程序能够正确执
行我们必须断言一个必需的前提条件如果这个条件为假即filename 等于0 断言
失败则程序将输出诊断消息然后终止
assert.h 是C 库头文件的C 名字C++程序可以通过C 库的C 名字或C++名字来使用它
这个头文件的C++名字是cassert C 库头文件的C++名字总是以字母C 开头后面是去掉后
缀.h 的C 名字正如前面所解释的由于在各种C++实现中头文件的后缀各不相同因
此标准C++头文件没有指定后缀
使用头文件的C 名字或者C++名字两种情况下头文件的#include 预处理器指示符的
效果也会不同下面的#include 指示符

QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
级别: 管理员
发帖
8532
金币
2762
威望
3231
贡献值
0
元宝
0
只看该作者 9楼 发表于: 2011-06-06


#include <cassert>
将cassert 的内容被读入到我们的文本文件中但是由于所有的C++库名字是在名字空间
std 中被定义的因而在我们的程序文本文件中它们是不可见的除非用下面的using 指示
符显式地使其可见
using namespace std;
使用C 头文件的#include 指示符
#include <assert.h>
就可以直接在程序文本文件中使用名字assert() 而无需使用using 指示符3 库文件厂
商用名字空间来控制全局名字空间污染即名字冲突问题以避免它们的库污染了用
户程序的名字空间8.5 节将讨论这些细节
1.4 注释
注释是用来帮助程序员读程序的语言结构它是一种程序礼仪可以用来概括程序的算
法标识变量的意义或者阐明一段比较难懂的程序代码注释不会增加程序的可执行代码
的长度在代码生成以前编译器会将注释从程序中剔除掉
C++中有两种注释符号一种是注释对/* */ 与C 语言中的一样注释的开始用/*
标记编译器会把/*与*/之间的代码当作注释注释可以放在程序的任意位置可以含有制
表符tab 空格或换行还可以跨越多行程序例如
/*
* 这是我们第一次看到++的类定义
* 类可用于基于对象和
* 面向对象编程中screen 类的
* 实现代码在第13 章中
*/
class Screen {
/* 此部分称为类体 */
public:
void home(); /* 将光标移到 0 0 */
void refresh(); /* 重绘Screen */
private:
/* 类支持"信息隐藏" */
/* 信息隐藏限制了程序 */
/* 对类的内部表示其数据的 */
/* 访问这是用"private" */
/* 来表示的 */
int height, width;
};
在代码中混杂过多的注释会使程序更难于理解例如注释几乎淹没了width 和height






的声明通常把注释放在要描述的文本之上比较合适与其他软件文档一样考虑到有效
性问题注释必须随着软件的发展而升级但是注释与所描述的代码随时间推移而渐行渐
远的情况却是经常发生的
注释对不能嵌套即一个注释对不能出现在另外一个注释对之中请尝试在系统中编译
下面的程序它会使大多数编译器无法正常处理
#include <iostream>
/*
* 注释对 /* */ 不能嵌套
* 这里不能嵌套几个字将被认为是代码
* 还包括接下来的这几行
*/
int main() {
cout << "hello, world\n";
}
解决这种嵌套注释的一个办法是在星号和斜线之间加一个空格
/ * * /
对于星号和斜线序列只有当这两个字符之间没有被空格分割时它们才被看作是注释

第二种注释符是双斜线// 它可用来注释一个单行程序行中注释符右边的内容都
将被当作注释而被编译器忽略例如下面的Screen 类使用了两种注释
/*
* 这是我们第一次看到C++的类定义
* 类可用于基于对象和
* 面向对象编程中Screen 类的
* 实现代码在第13 章中
*/
class Screen {
// 这部分被称为类体
public:
void home(); // 将光标移至 0,0
void refresh(); // 重绘Screen
private:
/* 类支持"信息隐藏" */
/* 信息隐藏限制了程序 */
/* 对类的内部表示其数据的 */
/* 访问这是用"private" */
/* 来表示的 */
// private 数据省略. . .
};
大多数程序往往包含两种格式的注释多行的说明通常被放在注释对中半行或单行的
注释则由双斜线指出

QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
描述
快速回复

您目前还是游客,请 登录注册
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容