用C++语言编程就是用C++语言描述和表达周围的现实世界。按照描述和表达现实世界的需要,本书共分为12章进行讲解。第1~7章为结构化编程,第8~11章为类和对象编程,第12章为C++标准库中的容器和算法框架。《C++面向对象程序设计实践教程》并没有罗列C++语言语法,而是通过实例仔细分析所有概念背后的基础思想、原理和技术,使读者从中获得学习的乐趣。本书适合从未有过编程经验但愿意努力学习程序设计的初学者。如果认真完成本书的学习,那么在程序设计领域已经有一个好的开始,可以写相对简单的程序,并能读复杂的程序,为进一步的学习打下良好的理论和实践基础。
编写背景
C++程序设计语言是由贝尔实验室的Bjarne Stroustrup(本贾尼·斯特劳斯特卢普)于20世纪80年代开发的,是一门非常优秀且被广泛应用的面向对象程序设计语言(Object-Oriented Programming Language),很多研究机构和公司都采用C++语言来开发各种高性能软件。掌握了C++语言,就为编程入门和进阶打下了牢固基础。
兴趣是最好的老师,因此,一本优秀的C++程序设计教材应该能够激发读者的学习兴趣。本书并没有罗列C++语言语法,而是通过实例仔细分析概念背后的基础思想、原理和技术,读者只有了解编程思想和原理后才能获得学习的乐趣。而且随着技术的发展,程序设计语言和编程工具会不断演化甚至被取代,只有思想和原理才能保持其重要性。
本书适合那些没有编程经验但愿意努力学习程序设计的初学者,帮助他们理解程序设计的基本原理并获得足够多的经验和实践技巧,以便更好地利用C++程序设计语言进行编程工作。
学习建议
对于C++语言初学者的第一个建议就是要多做实践练习。在这一点上,程序设计和其他需要实践学习的技能是很相似的。比如,不可能只通过看书就学会烹饪、开车、游泳等技能,同样,不动手编写程序也不可能真正学会程序设计。本书给出了大量代码实例,并配有详细的文字说明和图表,读者可以通过读写这些代码来理解程序设计的思想、概念和原理,并通过亲身体验编程中出现的错误,来理解C++语言的特性和语法规则。总之,在学习程序设计的过程中,不断编写代码、发现错误并进行修改的实践练习是不可替代的,而且,这也是学习的乐趣所在。
第二个建议是要有耐心。没有人可以一蹴而就。学习任何一种重要、有价值的技能,都要花费一些时间,而这是值得的。C++语言包含的内容很多,语法规则纷繁复杂,各种新概念层出不穷。本书遵循循序渐进的学习规律,每一章都本着简单实用的原则,介绍一些新的、有用的概念,并通过从实际应用中获取的例子来阐述这些概念。本书不刻意探究C++语言的语法细节,也没有重点介绍各种高深的编程技巧,而是从头到尾、一章章地逐步推进,读者通过程序代码表达思想的能力会逐步提高,对C++语言的掌握程度也会越来越深入。当然,也要经常回头对某些内容学习第二遍甚至第三遍,这是因为在遇到不理解的内容时,读者很可能会快速掠过,导致一些知识断层。本书每个章节的内容安排都假定读者已经理解了之前学过的内容。
第三个建议是不要投入大量精力去探究语法或技术细节。熟记所有的C++数据类型及使用规则也许会使你考个高分或显得很博学,但却对提高程序设计能力没有帮助,并且浪费了宝贵的时间和精力。就像很多人,即使有了汉英大字典,仍然不会写英语作文一样。最好的做法是尽量去理解程序背后的思想和原理,知道在什么情况下会遇到什么问题,应采用什么样的解决方案,以及为什么这么做是最好的。
第四个建议是多与他人一起学习和讨论问题。这是取得进步最直接也最有效的途径。团队讨论会帮助你表达思想,测试你对问题的理解程度,并巩固、加深学习记忆。本书中将有一个学习团队(3个志同道合但性格各异的学生)来共同解决一个小型的家庭账务管理项目。建议每个读者都能加入一个团队,进而参与到一个小型项目中。开发一个项目的过程,也就是编写一个完整的有用程序的过程。大多数人都会在项目开发中对程序设计产生浓厚的兴趣,进而学会如何把很多事情有效组织在一起。
最后一个建议是不要急切期盼“实际的”例子。本书中的每个实例都能直接说明一种语言特性或一个概念,而很多现实世界中的实例过于凌乱,所能展示的知识也不如书中的实例多。数十万行代码的商业程序中所采用的技术在书中用几行或几十行代码的程序同样能展现出来。最好的理解现实世界的途径就是好好研究一些基础小程序。记住:麻雀虽小,五脏俱全。
如果读者能认真完成本书的学习,可以期待已经在程序设计领域有了一个好的开始,可以编写相对简单的程序,并能读懂复杂的程序,且为进一步学习打下良好的理论和实践基础。
本书特色
1. 每章都包含“本章要点”和“本章小结”部分,以帮助读者明确全章的学习内容。
2. 部分章包含星号标记的选读小节,这部分内容可以跳过而不会影响全书的连贯性,它们是为那些自学能力强且渴望挑战的学生准备的。
3. 课后的练习题包括填空题、简答题、编程题和独具匠心的提升练习。提升练习部分均为生活中的实际课题,如环境污染、中国人健康指数计算、人口增长、计算机辅助教学、民意测评等,其中的部分内容在前后章节中具有一定的延续性。
4. 本书的配套资料包含课件、实例源代码、部分练习题及编程练习答案。书中的源代码可以自由修改、编译,以符合自己的需要。
5. 本书按照读者在学习程序设计中遇到的问题来组织内容,随着读者对程序设计的理解和实际动手能力的提高,一个主题一个主题地平滑向前推进。本书的叙述顺序更像一部小说,而不是一部字典。
6. 本书每个知识点和技术要点都给出了典型实例和代码分析,这些代码不仅能够一针见血地指明技术要点的本质,而且短小精炼,方便读者自行尝试。
7. 本书以一个家庭账务管理系统项目案例贯穿始终,第2~6章、第8章、第9章和第12章的最后一节都是本项目部分功能的实现。每章中的知识点则使用独立的例子,并辅以实例输出和代码分析,以阐述该章介绍的主题,并在讨论主题的过程中逐步解决这个案例。
8. 本书虚拟了几个人物,在每章最后通过一些有趣的对话,总结C++语言正确的学习方法。通过一些错误的例子和实际的错误代码来进行改正,这是本教材的一大特色。
内容摘要
用C++语言编程,本质上就是用C++语言描述和表达周围的现实世界。按照描述和表达现实世界的需要,本书可以简单地分为3个部分:结构化编程、面向对象的编程和标准库编程。
结构化编程部分简要介绍C++语言的发展和特点、标准库的知识、基本数据类型、分支和循环控制结构、基本过程化单元——函数的定义和使用方法,以及数组和指针的实现和使用。通过基本数据类型学习,读者将学会使用int、double、string等数据类型来描述现实世界中的数据;通过逻辑控制语句学习,读者将学会使用if-else来控制程序逻辑;通过函数学习,读者将学会使用函数来表达完整的算法。
面向对象编程部分重点讨论了类和对象、组合和继承、多态与虚拟函数、运算符重载和泛型程序设计等内容,以循序渐进的方式介绍封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism)这3种面向对象语言的主要技术。本部分中,借助许多有意义的范例程序,将讲解抽象化、派生类所定义对象的构造和析构次序、混合组合和继承以建立新的类、重载虚拟函数、虚拟析构函数等被大部分C++书籍忽略的内容。面向对象的思想将帮助读者抽象现实世界,而类和对象则帮助读者将抽象的结果在程序中表达出来。
标准库编程部分关注标准库中的容器和算法框架。泛型程序设计就是将程序写得尽可能通用,简单而优雅,同时不损失效率。本部分展示了C++标准模板库STL中的容器(如向量)是如何实现的,以及如何使用它们,还展示了常见的标准库算法(如查找、排序等);简要介绍了一些概念、术语及主要组件的使用方法,目的是使读者对STL与泛型程序设计有一个概要性的了解。
上述内容都是C++语言中最基本又最实用的部分,通过对这些内容的学习,读者完全可以自如地用C++语言来描述和表达现实世界。
建议和反馈
没有绝对完美的教材(因为每个人的需求和评价角度总是差别很大),但我们会尽力使本书的内容及其支持材料接近于完美。脱离读者是不可能写出好教材的,为此我们需要大家的反馈。欢迎广大读者对本书的内容、结构、案例等提出反馈意见,以使我们在下一版中能及时做出更正、补充或修改。读者在学习过程中如果有什么疑问或对本书有任何建议,可通过发送电子邮件(lcrlj@126.com)与我们联系。
作者分工
本书第1~6章由吴迪编写,第7章和第12章由魏连锁编写,第8~11章由李长荣编写,各章的家庭账务管理系统案例由李长荣编写,全书例题由吴迪和魏连锁调试通过。课题组老师也参与了部分内容的编写工作。
第1章 C++语言概述1
1.1 为什么要学习程序设计1
1.2 C++语言历史2
1.3 C++语言特点3
1.4 C++语言程序设计风格4
1.4.1 结构化程序设计4
1.4.2 面向对象程序设计5
1.4.3 泛型程序设计7
1.5 标准库8
1.5.1 标准库简介8
1.5.2 标准模板库8
习题10
第2章 第一个C++程序13
2.1 程序13
2.2 入门实例14
2.3 实例分析15
2.3.1 注释15
2.3.2 使用空白字符16
2.3.3 包含其他文件16
2.3.4 命名空间17
2.3.5 定义main()函数18
2.3.6 使用标准输入和输出18
2.3.7 字符串20
2.3.8 语句的终止20
2.3.9 从main()函数返回值20
2.4 编译C++语言程序21
2.5 链接23
2.6 编程环境23
2.7 家庭账务管理系统——启动界面24
习题26
第3章 数据类型29
3.1 数据类型29
3.1.1 整数类型31
3.1.2 浮点类型33
3.1.3 字符类型34
3.1.4 布尔类型35
3.1.5 空类型35
3.1.6 枚举类型35
3.2 关键字36
3.3 常量36
3.3.1 什么是常量36
3.3.2 为什么需要常量37
3.3.3 使用常量37
3.4 变量38
3.4.1 什么是变量38
3.4.2 变量的定义39
3.4.3 变量的命名39
3.4.4 变量的赋值40
3.5 结构体42
3.5.1 结构体类型的定义和初始化42
3.5.2 结构体变量的使用43
3.6 家庭账务管理系统——用户信息45
习题48
第4章 控制语句51
4.1 控制结构52
4.2 选择语句52
4.2.1 布尔表达式和关系运算符53
4.2.2 单路选择if语句54
4.2.3 双路选择if语句55
4.2.4 多路选择if语句56
4.2.5 switch选择语句58
4.2.6 选择结构的条件表达式62
4.3 循环语句63
4.3.1 for循环64
4.3.2 for循环的嵌套66
4.3.3 无限循环68
4.3.4 while循环语句69
4.3.5 do-while循环语句71
4.3.6 几种循环方式的比较72
4.4 转向语句73
4.4.1 break语句73
4.4.2 continue语句73
4.4.3 goto语句74
4.5 家庭账务管理系统——主菜单76
习题79
第5章 函数81
5.1 函数简介81
5.2 C++程序组件82
5.3 函数命名83
5.4 void函数的声明、定义和调用83
5.5 返回值函数86
5.6 参数传递88
5.6.1 形参和实参89
5.6.2 向函数传递参数89
5.6.3 值传递和引用传递90
5.6.4 传递多个参数93
5.7 内联函数95
5.8 函数重载96
5.9 家庭账务管理系统——设置窗口标题函数97
习题100
第6章 数组与字符串103
6.1 数组的概念103
6.2 数组的声明104
6.3 数组的初始化107
6.4 数组作为函数的参数111
6.5 二维数组的声明与初始化114
6.6 二维数组作为函数参数117
6.7 字符串119
6.7.1 类C字符串120
6.7.2 string字符串122
6.8 家庭账务管理系统的系统登录123
习题128
第7章 指针130
7.1 指针的概念130
7.2 变量与指针131
7.3 数组与指针134
7.4 指针与引用137
7.5 函数与指针138
7.5.1 作为函数参数的指针138
7.5.2 函数指针139
7.5.3 指针函数141
7.6 使用const修饰指针143
7.7 动态内存分配146
7.8 链表149
习题153
第8章 类和对象155
8.1 面向过程程序设计和面向对象程序设计156
8.2 类和对象的关系156
8.3 声明类类型157
8.3.1 使用struct声明类和使用class声明类157
8.3.2 对类的成员进行访问159
8.3.3 类的get和set方法159
8.4 类的成员函数162
8.4.1 成员函数的性质162
8.4.2 在类外定义成员函数162
8.4.3 inline成员函数164
8.5 类声明与成员函数定义分离165
8.6 构造函数168
8.6.1 什么是构造函数168
8.6.2 对象的初始化168
8.6.3 构造函数的作用169
8.6.4 带参数的构造函数171
8.6.5 用参数初始化表对数据成员初始化172
8.6.6 构造函数的重载173
8.6.7 使用默认参数值的构造函数174
8.7 析构函数176
8.8 公有数据的保护179
8.8.1 常对象成员179
8.8.2 常对象182
8.9 静态成员184
8.9.1 静态数据成员184
8.9.2 静态成员函数186
8.10 示例程序:时间标记类188
8.11 家庭账务管理系统——用户实体类192
习题199
第9章 继承与派生202
9.1 继承和派生的概念202
9.2 派生类的声明方式204
9.3 派生类的继承方式206
9.4 派生类的构造函数和析构函数207
9.4.1 派生类的构造函数207
9.4.2 派生类的析构函数209
9.5 使用继承必须满足的逻辑关系211
9.6 继承在软件开发中的重要意义212
9.7 家庭账务管理系统——添加账目及账目查询213
习题219
第10章 多态性和虚函数221
10.1 多态性的概念221
10.2 虚函数222
10.2.1 虚函数的作用222
10.2.2 运行期绑定和编译期绑定225
10.2.3 虚函数使用方法226
10.2.4 构造函数与析构函数227
10.2.5 什么情况下声明虚函数229
10.3 纯虚函数和抽象类230
10.3.1 纯虚函数230
10.3.2 抽象类233
习题236
第11章 运算符重载238
11.1 运算符重载的概念238
11.2 运算符重载的方法240
11.3 基本运算符重载243
11.4 友元函数244
11.5 赋值运算符重载246
11.6 输入与输出运算符的重载249
11.7 特殊运算符的重载251
11.7.1 下标运算符的重载251
11.7.2 自增与自减运算符的重载254
11.7.3 类型转换运算符的重载256
习题260
第12章 模板与STL261
12.1 为什么使用模板261
12.2 函数模板263
12.3 类模板267
12.4 STL271
12.4.1 STL的组成272
12.4.2 在程序中使用STL273
12.5 容器276
12.5.1 vector容器277
12.5.2 list容器280
12.5.3 set容器283
12.5.4 map容器285
12.6 算法287
12.6.1 非变序型算法287
12.6.2 变序型算法289
12.6.3 排序算法291
12.6.4 数值算法294
12.7 家庭账务管理系统——STL的应用295
12.7.1 STL的vector的应用295
12.7.2 用户账目信息及个人信息的持久化保存297
习题301