前一时期,人们编写的程序多是面向过程的,设计者必须充分地考虑到程序的每一个细节,要指定程序在每一瞬时应执行的动作。C语言是面向过程的结构化和模块化的语言,用于处理小型问题时得心应手,但在处理大型问题时就显得力不从心了。为了处理大型程序的需要,计算机科学家提出了面向对象程序设计的理论,并于20世纪末期在C语言的基础上研制出支持面向对象的C++语言,为处理大程序提供了有力的工具。
近年来,国内许多大学的计算机类专业都开设了C++程序设计课程,一些大学的非计算机专业也开设了C++面向对象程序设计课程,许多学过C语言程序设计的人也想了解和学习C++和面向对象程序设计的有关知识。但是,由于C++涉及概念很多,语法比较复杂,内容十分广泛,使不少人感到学习难度较大,难以入门。
在许多读者的要求和鼓励下,作者于2004年完成了《C++程序设计》一书的编写工作,由清华大学出版社出版并向全国发行。该书以未学过C语言的读者为对象,从面向过程入手介绍程序设计的基本知识和方法,然后介绍用C++进行面向对象程序设计的方法。该书出版后,由于概念清晰,通俗易懂,受到师生们的欢迎和好评,几年内发行了30多万册。
目前在大学理工类专业,普遍开设了C语言程序设计的课程,许多学生在学习C语言后希望对C++面向对象程序设计有所了解,以便日后在需要时能较快地进入该领域。很多师生希望我能出版一本以C语言为起点的C++教材。
为此,2006年我在清华大学出版社出版了《C++面向对象程序设计》一书。该书是在《C++程序设计》一书的基础上编写而成的。考虑到本书的读者已学习过C语言程序设计,因此不必再重新学习面向过程程序设计的部分,而直接从面向对象程序设计入手,将《C++程序设计》一书中介绍面向对象程序设计的内容抽出来改写后单独成书,并且重新写了第1章,介绍C++面向对象程序设计的初步知识以及C++对C在面向过程程序设计方面的改进与增强,为以后各章的学习打下基础。这样的安排使本书内容更集中,篇幅更紧凑。本书仍然保持了通俗易懂、贴近读者、容易入门的特点。希望有助于大学生学习C++课程,初步掌握面向对象程序设计的方法。
经过几年的教学实践后,作者现在对此书进行修订,出版了《C++面向对象程序设计(第2版)》,即本书。现对本书的指导思想作以下的说明。1. 教材应当准确定位,合理取舍内容
首先要弄清楚教材是为什么人写的,他们学习C++的目的是什么,应当学到什么程度,不能无的放矢。应当声明: 本书的对象不是C++的专业开发人员,而是高校各专业的大学生,他们并无从事程序设计的实际经验,将来也不一定是C++的专业开发人员。众所周知,研制C++的初衷是为了解决大型软件开发中遇到的问题,提高软件的开发效率。只有参加过研制大型软件的人才会真正体会到C++的优越性,并善于利用C++的独特机制去进行软件开发。
大学生在学校学习期间学习C++的目的是了解面向对象程序设计方法,能够利用C++编写相对简单的程序,为以后进一步学习和应用打下良好的基础。不可能设想,通过几十小时的学习,就能使一个没有程序设计基础的初学者变成一个熟练的C++开发人员。应当有一个实事求是的分析和估计。因此,本书着力于使读者对C++的全貌和作用有基本的认识,用容易理解的方法讲清楚有关的基本概念和基本方法,而不去罗列C++语法中各种烦琐的细节;否则将会使篇幅过大(许多国外的书厚达近千页),而且会冲淡重点,主次不分,使读者感到枯燥无味。
2. 要设计合适的教材体系
C++程序设计牵涉面向对象程序设计的理论、C++语言的语法以及算法3个方面的内容,其中每一方面都包含十分丰富的内容,都可以分别单独成书。显然在一本教材中深入、详细地介绍以上3个方面的知识是不可能的,必须把它们有机地结合起来,综合应用。不同的书对此采取不同的写法,侧重点有所不同,各有优缺点,适合于不同的读者,需要在教学实践中检验,取长补短,不断完善。
作者认为,要进行C++程序设计当然需要了解面向对象程序设计的有关概念,但是本课程毕竟不是一门面向对象程序设计的理论课程,在本书中不是抽象地介绍面向对象程序设计的理论,而是在介绍C++语言的特点和应用过程中,自然地引出面向对象程序设计的有关概念,通过C++的编程过程理解面向对象程序设计方法。在各章中结合例题介绍有关的算法,引导读者思考怎样构造一个算法。
要用C++编写程序,最基本的要求是正确掌握和运用C++。由于C++语法复杂,内容又多,如果对它缺乏系统了解,将难以真正应用,编写出来的程序将会错误百出,通不过编译,事倍功半。本书的做法是全面而系统地介绍C++的主要特点和功能,引导读者由简到繁地学会编写C++程序。有了C++编程的初步基础后,再进一步提高。这样的方法可能符合大多数学习者的情况,降低了学习难度。
3. C++教材应当体现C++标准
C++是从C语言发展而来的,为了与C兼容,C++保留了C的许多用法,人们在编写C++程序时也常常沿用C的某些传统用法。例如主函数为void类型,无返回值;头文件带后缀.h;使用系统库时不使用命名空间等。但是,ANSI C++标准在一些方面有新的规定,例如要求主函数为int类型,如果程序正常执行则返回0值;系统头文件不带后缀.h;使用系统库时使用命名空间std;增加了字符串类型string等。
虽然C++仍然允许使用从C继承来的传统用法,但作者认为,作为教材,应提倡C++的新方法。应当引导读者从一开始就按照C++标准编写程序,养成C++的编程风格。本书各章都是依据C++标准介绍的,同时也说明允许使用的C的用法。在本书中,程序的形式大致如下:#include<iostream>//头文件不带后缀.h
#include<string> //包含string头文件,以便能在程序中使用字符串变量
using namespace std; //使用系统库时使用命名空间std
int main() //主函数为int类型
{
string str; //可以定义字符串变量str
return 0; //程序正常执行则返回0
}4. 化解难点,使读者学习C++更容易
作者在写作过程中花了很大的精力去考虑怎样使读者易于接受和理解。作者一贯认为,教材编著者应当与读者将心比心,换位思考,要站在读者的立场上思考问题,帮助他们排除学习中的困难,要善于把复杂的问题简单化,而不应当把简单的问题复杂化,要善于化解难点,深入浅出。不要让读者被一大堆高深莫测的名词术语吓住,有些问题看起来很深奥,其实换一个角度去解释就很容易理解,甚至用一个通俗的例子就把问题说清楚了。
本书用通俗易懂的方法和语言叙述复杂的概念。传统的教学三部曲是:“提出概念—解释概念—举例说明”,作者在多年的计算机教学实践中,采用了新的三部曲:“提出问题—分析和解决问题—归纳分析”。从具体到抽象,从实际到理论,符合初学者的认知规律。本书在引入每一个程序时,都按照以下几个步骤展开:提出问题—编写程序—运行结果—程序分析。由浅入深,逐步展开。
本书便于自学,即使没有老师讲解,读者也能看懂本书的大部分内容。这样,老师教学时就可以不必完全按照教材的内容和顺序详细讲解,而可以选择重点讲授,其余内容由学生自学。
5. 本教材中的程序,是从教学的角度考虑的
本书中的程序是为了帮助读者更好地理解某一方面的教学内容而专门编写的,并不一定是实际应用的程序。一个实际的C++程序需要考虑许多因素,综合各部分知识,有许多注释行,而且一般是多文件的程序,篇幅较长,往往不适合作为教学程序。教学程序对问题进行了简化,尽量压缩不必要的语句,减少注释行,篇幅一般不长,力求使读者能读懂程序。
有些在专业人员看来很“幼稚”的程序,对初学者来说可能是一个很合适的教学用例。不要忘记,教材的任务是用读者容易理解的方法讲清基本的概念和方法。在初步掌握C++编程方法后,可以逐步使程序复杂一些,长一些,更接近真实程序一些。各章中的习题与例题相比,会复杂一些。在学完本课程后,最好完成一个实际的应用程序,以提高实际应用的能力。
6. 要有相应的配套教学参考用书,以满足不同的需要
考虑到不同学校、不同专业、不同读者对学习C++有不同的要求,因此提供配套用书,不同的读者可以根据要求选用。本书有两本配套的教学参考书:
(1) 《C++面向对象程序设计题解与上机指导(第2版)》,清华大学出版社出版。该书提供主教材各章中的全部习题的解答。由于教材的篇幅有限,有些很好的例子无法在教材中列出,我们把它们作为习题,希望读者自己完成,教师也可以从中选择一些习题作为例题讲授。学生除了完成教师指定的习题外,最好把习题解答中的程序看一遍,以更好地理解C++程序,扩大眼界,启迪思路,丰富知识,增长能力。
程序设计是一门实践性很强的课程,只靠听课和看书是学不好的。衡量学习好坏的标准不是“懂不懂”,而是“会不会干”。因此必须强调多编程,多上机实践。在《C++面向对象程序设计题解与上机指导(第2版)》中,还介绍了运行C++程序的方法。此外,书中还给出上机实践任务,要求学生完成若干次上机实践。
本书还提供全部例题的源程序,以便于教师讲授,也便于学生在此基础上调试和修改程序,以学得更灵活深入,可在清华大学出版社网站www.tup.com.cn下载。
(2) 《C++程序设计实践指导》,清华大学出版社出版。该书提供了一批具有实用价值的C++应用程序。这是为学习教材后进一步深入学习的读者准备的,目的是提高编程能力。
这样,在学习本课程时就有3个台阶: 主教材介绍的是引导入门的基础例题,相对简单,容易理解;《C++面向对象程序设计题解与上机指导(第2版)》中的习题解答实际上是一批难度高于例题的程序,使学习更深入;《C++程序设计实践指导》中提供的是实用或接近实用的程序,可供实际编程参考。
有的专业对学生使用C++编程有一定要求,可以在学完课程后,安排一段集中的时间进行一次编程实践,相当于课程设计。该书内容包括: 怎样编写C++应用程序;提供若干个不同规模的实际的C++应用程序供分析阅读;安排并指导学生完成1~2个C++应用程序。经过这样的训练,学生的实际能力将会有较大的提高。
此外,还向使用本书的教师免费提供讲课的电子演示文稿(素材),以节省教师的备课时间。
本书由谭浩强教授编写,谭亦峰和薛淑斌高级工程师参加了写作思路的研讨、收集资料、调试部分程序等工作。全国高等院校计算机基础教育研究会和浩强工作室的各位专家以及全国各高校老师多年来对作者始终给予了热情的支持和鼓励。清华大学出版社对本书的出版十分重视并作了周到的安排,使本书得以在短时间内出版。对于曾经鼓励、支持和帮助过我的朋友,谨表示真挚的谢意。
本书肯定会有不妥之处,诚盼专家和广大读者不吝指正。
目录
- 第1章C++的初步知识1
- 1.1从C到C++1
- 1.2最简单的C++程序2
- 1.3C++对C的扩充8
- 1.3.1C++的输入输出8
- 1.3.2用const定义常变量11
- 1.3.3函数原型声明11
- 1.3.4函数的重载12
- 1.3.5函数模板14
- 1.3.6有默认参数的函数16
- 1.3.7变量的引用17
- 1.3.8内置函数24
- 1.3.9作用域运算符25
- 1.3.10字符串变量26
- 1.3.11动态分配/撤销内存的运算符new和delete29
- 1.3.12C++对C功能扩展的小结30
- 1.4C++程序的编写和实现31
- 1.5关于C++上机实践32
- 习题33
- 第2章类和对象的特性36
- 2.1面向对象程序设计方法概述36
- 2.1.1什么是面向对象的程序设计36
- 2.1.2面向对象程序设计的特点39
- 2.1.3类和对象的作用40
- 2.1.4面向对象的软件开发41
- 2.2类的声明和对象的定义43
- 2.2.1类和对象的关系432.2.2声明类的类型43
- 2.2.3定义对象的方法45
- 2.2.4类和结构体类型的异同47
- 2.3类的成员函数48
- 2.3.1成员函数的性质48
- 2.3.2在类外定义成员函数48
- 2.3.3内置成员函数(inline成员函数)49
- 2.3.4成员函数的存储方式51
- 2.4对象成员的引用52
- 2.4.1通过对象名和成员运算符访问对象中的成员53
- 2.4.2通过指向对象的指针访问对象中的成员53
- 2.4.3通过对象的引用来访问对象中的成员54
- 2.5类和对象的简单应用举例54
- 2.6类的封装性和信息隐蔽61
- 2.6.1公用接口与私有实现的分离61
- 2.6.2类声明和成员函数定义的分离62
- 2.6.3面向对象程序设计中的几个名词65
- 习题66
- 第3章怎样使用类和对象68
- 3.1利用构造函数对类对象进行初始化68
- 3.1.1对象的初始化68
- 3.1.2用构造函数实现数据成员的初始化69
- 3.1.3带参数的构造函数71
- 3.1.4用参数初始化表对数据成员初始化73
- 3.1.5构造函数的重载74
- 3.1.6使用默认参数的构造函数76
- 3.2利用析构函数进行清理工作79
- 3.3调用构造函数和析构函数的顺序81
- 3.4对象数组83
- 3.5对象指针85
- 3.5.1指向对象的指针85
- 3.5.2指向对象成员的指针85
- 3.5.3指向当前对象的this指针88
- 3.6共用数据的保护90
- 3.6.1常对象90
- 3.6.2常对象成员91
- 3.6.3指向对象的常指针93
- 3.6.4指向常对象的指针变量93
- 3.6.5对象的常引用96
- 3.6.6const型数据的小结97
- 3.7对象的动态建立和释放98
- 3.8对象的赋值和复制99
- 3.8.1对象的赋值99
- 3.8.2对象的复制101
- 3.9静态成员103
- 3.9.1静态数据成员104
- 3.9.2静态成员函数106
- 3.10友元109
- 3.10.1友元函数109
- 3.10.2友元类113
- 3.11类模板114
- 习题118
- 第4章对运算符进行重载122
- 4.1为什么要对运算符重载122
- 4.2对运算符重载的方法124
- 4.3重载运算符的规则127
- 4.4运算符重载函数作为类成员函数和友元函数128
- 4.5重载双目运算符132
- 4.6重载单目运算符137
- 4.7重载流插入运算符和流提取运算符139
- 4.7.1重载流插入运算符“<<”140
- 4.7.2重载流提取运算符“>>”142
- 4.8有关运算符重载的归纳144
- 4.9不同类型数据间的转换145
- 4.9.1标准类型数据间的转换145
- 4.9.2用转换构造函数进行不同类型数据的转换145
- 4.9.3类型转换函数147
- 习题153
- 第5章继承与派生154
- 5.1什么是继承与派生154
- 5.2派生类的声明方式157
- 5.3派生类的构成157
- 5.4派生类成员的访问属性159
- 5.4.1公用继承160
- 5.4.2私有继承162
- 5.4.3保护成员和保护继承165
- 5.4.4多级派生时的访问属性169
- 5.5派生类的构造函数和析构函数170
- 5.5.1简单的派生类的构造函数171
- 5.5.2有子对象的派生类的构造函数174
- 5.5.3多层派生时的构造函数177
- 5.5.4派生类构造函数的特殊形式179
- 5.5.5派生类的析构函数180
- 5.6多重继承180
- 5.6.1声明多重继承的方法181
- 5.6.2多重继承派生类的构造函数181
- 5.6.3多重继承引起的二义性问题184
- 5.6.4虚基类187
- 5.7基类与派生类的转换192
- 5.8继承与组合195
- 5.9继承在软件开发中的重要意义197
- 习题198
- 第6章多态性与虚函数203
- 6.1什么是多态性203
- 6.2一个典型的例子204
- 6.3利用虚函数实现动态多态性209
- 6.3.1虚函数的作用209
- 6.3.2静态关联与动态关联213
- 6.3.3在什么情况下应当声明虚函数215
- 6.3.4虚析构函数215
- 6.4纯虚函数与抽象类217
- 6.4.1纯虚函数217
- 6.4.2抽象类217
- 6.4.3应用实例218
- 习题225
- 第7章输入输出流226
- 7.1C++的输入和输出226
- 7.1.1输入输出的含义226
- 7.1.2C++的I/O对C的发展——类型安全和可扩展性226
- 7.1.3C++的输入输出流227
- 7.2标准输出流232
- 7.2.1cout,cerr和clog流232
- 7.2.2标准类型数据的格式输出234
- 7.2.3用流成员函数put输出字符239
- 7.3标准输入流240
- 7.3.1cin流240
- 7.3.2用于字符输入的流成员函数242
- 7.3.3istream类的其他成员函数245
- 7.4对数据文件的操作与文件流249
- 7.4.1文件的概念249
- 7.4.2文件流类与文件流对象250
- 7.4.3文件的打开与关闭251
- 7.4.4对ASCII文件的操作253
- 7.4.5对二进制文件的操作258
- 7.5字符串流264
- 习题268
- 第8章C++工具270
- 8.1异常处理270
- 8.1.1异常处理的任务270
- 8.1.2异常处理的方法271
- 8.1.3在函数声明中进行异常情况指定278
- 8.1.4在异常处理中处理析构函数279
- 8.2命名空间281
- 8.2.1为什么需要命名空间281
- 8.2.2什么是命名空间284
- 8.2.3使用命名空间解决名字冲突286
- 8.2.4使用命名空间成员的方法288
- 8.2.5无名的命名空间290
- 8.2.6标准命名空间std290
- 8.3使用早期的函数库291
- 习题292
- 附录A常用字符与ASCII代码对照表294
- 附录B运算符和结合性295
- 参考文献297
- 第14章实验安排220
- 14.1实验1C程序的运行环境和运行C程序的方法220
- 14.2实验2最简单的C程序设计——顺序程序设计222
- 14.3实验3选择结构程序设计224
- 14.4实验4循环结构程序设计225
- 14.5实验5利用数组(一)226
- 14.6实验6利用数组(二)227
- 14.7实验7函数调用(一)228
- 14.8实验8函数调用(二)229
- 14.9实验9善用指针(一)230
- 14.10实验10善用指针(二)231
- 14.11实验11使用结构体232
- 14.12实验12文件操作233
- 参考文献234