内容简介
作为C++入门经典教材,本书结合作者多年的教学经验,清楚梳理出一个有利于教与学的结构体系,从各章开头的内容总览,到随处可见的自测题、小结框、编程提示和编程陷阱,再到章末的小结、习题、编程练习和编程项目,由浅入深,从简到繁,可以帮助初学者渐入佳境,逐步理解并掌握重要的编程概念。
全书共18章,8个附录。在讲解C++基础知识之后,循序渐进地引导读者深入函数、I/O流、类、控制流程、命名空间、数组、字符串、指针和动态数组、递归、模板、指针和链表、派生类、异常以及标准模板库。本书前几版被全国100多所高校选作C++程序设计课程的教材,很受师生欢迎。本书也适合自学,不同层次的知识点和测试练习,可以帮助读者以自己的节奏进入美妙的C++编程世界。
前 言
本书适合C++程序设计和计算机科学入门课程。不要求读者有任何编程经验,也不要求掌握除中学代数之外的其他任何数学知识。
本书前几版的读者请阅读关于第10版修订内容的小节,前言其余内容可略过。新读者请阅读前言的全部内容以把握本书脉络。
第10版修订内容
第10版采用和第9版相同的体例。保留第9版全部内容,但进行了以下修订。
* 统一采用camelCase拼写法,不再采用C风格的下划线连接。例如,set_name改为setName。
* 第10章讨论了浅拷贝和深拷贝。
* 第12章和第17章讨论了如何用头文件引入编译模板。
* 第18章讨论了C++11的std::array类、正则表达式、线程和智能指针。
* 进行了大量勘误和编辑,强调了文件I/O的首选方法,术语更规范,更好地定义了封装,并不再讨论已在C++11和更高版本中成为标准的一些东西。
* 新增10个编程项目。
* 新增5个视频讲解,总数达69个。这些视频讲解辅导学生解题和写程序,有助于巩固对关键编程概念的掌握。如书中某个主题有对应的视频讲解,就会出现一行特殊的注释(视频讲解:……)。
用过第9版的教师可沿用以前的教案,几乎不需要任何改动。
主题可以灵活排序
本书允许教师自由安排教学顺序。为了演示这一灵活性,下面推荐了两个额外的顺序。采用任何顺序都不会影响学习的连贯性。为了在改变顺序时确保这种连贯性,可能需要移动个别小节而不是全章。但只有较大的、位置便利的小节才需移动。为了帮助您根据需要自定义一个教学/阅读顺序,图P.1展示了一幅依赖图。另外,每章都有“预备知识”小节,解释学习那一章的每一节之前需掌握的内容。
重新排序1:提前学习类
为有效设计类,学生需要掌握一些基本工具,比如控制结构和函数定义。这些基础知识在第1章~第6章介绍。完成第6章后,学生就可开始写自己的类了。如果想提前学习类的相关知识,可像下面这样重新安排各章顺序。
* 基础知识 第1章~第6章。这6章全面介绍控制结构、函数定义和基本文件I/O。第3章介绍几种额外的控制结构,想提前学习类可考虑推迟这一章。
* 类和命名空间 第10章、第11章的11.1节和11.2节、第12章。这些章节全面介绍了如何定义类、友元、重载操作符和命名空间。
* 数组、字符串和向量 第7章和第8章。
* 指针和动态数组 第9章。
* 类中的数组 第11章的11.3节和11.4节。
* 继承 第15章。
* 递归 第14章(可推迟)。
* 指针和链表 第13章。
可能还要用到以下各章的部分内容。
* 异常处理 第16章。
* 模板 第17章。
* 标准模板库 第18章。
重新排序2:略微推迟类的学习
在“重新排序2”中,将先学完所有控制结构和数组的知识,然后才开始学习类。虽然对类的接触要比“重新排序1”晚,但还是比本书的默认顺序提前一些。
* 基础知识 第1章到第6章。这6章全面介绍了控制结构、函数定义和基本文件I/O。
* 数组和字符串 第7章、第8章的8.1节和8.2节。
* 类和命名空间 第10章、第11章的11.1节、11.2节和第12章。这些章节全面介绍了如何定义类、友元、重载操作符和命名空间。
* 指针和动态数组 第9章。
* 类中的数组 第11章的11.3节和11.4节。
* 继承 第15章。
* 递归 第14章(可推迟)。
* 向量 8.3节。
* 指针和链表 第13章。
可能还要用到以下各章的部分内容。
* 异常处理 第16章。
* 模板 第17章。
* 标准模板库 第18章。
面向学生的易用性
一本书必须按恰当的顺序来讲解恰当的主题,这是最起码的要求。另外,在老师和其他有经验的程序员看来,书的内容必须清晰而正确,这是另一个最起码的要求。但是不是符合这两项要求的书都是好书呢?答案是否定的。书中的内容必须采取有利于初学者使用的方式来编排。在这本入门教科书中,我尽力让学生觉得清楚和友好。本书以前版本的大量学生反馈证明,这种写作风格确实使内容更清晰,能使学生充分享受到学习的乐趣。
ANSI/ISO C++标准
本书可顺利使用符合最新ANSI/ISO C++标准的编译器。写作时最新标准是C++14。
高级主题
许多“高级主题”都已成为标准CS1课程的一部分。即使不是,以补充材料的形式提供也不错。本书提供大量高级主题,它们既可集成到课程中,也可作为自学主题。本书全面讲述了C++模板、继承(包括虚函数)、异常处理和STL(Standard Template Library,标准模板库)。虽然本书使用了库,而且教给学生库的重要性,但不要求任何非标准库。本书只用所有C++实现都有的库。
依赖图
下面的依赖图展示了各个章节可能的排序方式。连接两个框的实线表明上部的框必须先于下部的框完成。只要符合这个条件,采用任何阅读顺序都无损连贯性。如果一个框中包含小节编号,表明该框只代表那些小节,不代表全章。
小结框
每个要点都用一个有底纹的方框来小结,它们散布于各章。
自测题
每章都在重要位置提供大量自测题。答案在章末提供。
视频讲解
视频讲解(Video Note)旨在讲解关键编程概念和技术,演示了从设计到编码来解决问题的过程。视频讲解使学生能方便地自学感兴趣的主题,支持选择、播放、倒退、快进和暂停。每当看到“ 视频讲解:……”,都表明当前主题有对应的视频讲解。视频列表请从本书中文版配套网站获取,网址是http://transbot.ys168.com和https://pan.baidu.com/s/1yd43W。注意,由于是英文视频,所以为了方便索引,书中保留了这些视频的英文名称。
支持材料
部分支持材料本书所有读者都适合。其他仅适合认证教师。
适合本书所有读者的支持材料
* 源代码
* PowerPoint幻灯片
* 视频讲解
获取这些材料请访问本书译者博客(transbot.blog.163.com)或网盘(http://transbot.ys168.com和https://pan.baidu.com/s/1yd43W)。
适合认证教师的资源
选用本书作为教材的教师,可致函责编信箱coo@netease.com,了解详情。
* 教师资源指南(Instructor’s Resource Guide):包括每一章的教学要点、课堂测验/答案和大量编程项目的参考答案。
* Test Bank和Test Generator:用于生成试卷。
* PowerPoint幻灯片:包括本书的程序和插图。
* Lab Manual(实验手册)。
致 谢
在准备本书素材期间,许多个人和团体提供了大量建议和帮助,并和我进行了广泛而深入的探讨。本书第1版大部分内容是我在科罗拉多大学(波德分校)计算机系担任客座教授时写就的。其余内容和后续版本则是在加州大学(圣地亚哥分校)计算机科学与工程系完成的。非常感谢两所学校为本书写作和教学所提供的良好氛围。
特别感谢向这一版和之前各版提供意见或者编程项目的个人,以下人名按字母排序:Alex Feldman,Amber Settle,Andrew Burt,Andrew Haas,Anne Marchant,Barney MacCabe,Bob Holloway,Bob Matthews,Brian R. King,Bruce Johnston,Carol Roberts,Charles Dowling,Claire Bono,Cynthia Martincic,David Feinstein,David Teague,Dennis Heckman,Donald Needham,Doug Cosman,Dung Nguyen,Edward Carr,Eitan M. Gurari,Ethan Munson,Firooz Khosraviyani,Frank Moore,Gilliean Lee,Huzefa Kagdi,James Stepleton,Jeff Roach,Jeffrey Watson,Jennifer Perkins,Jerry Weltman,Joe Faletti,Joel Cohen,John J. Westman,John Marsaglia,John Russo,Joseph Allen,Joseph D. Oldham,Jerrold Grossman,Jesse Morehouse,Karla Chaveau,Ken Rockwood,Larry Johnson,Len Garrett,Linda F. Wilson,Mal Gunasekera,Marianne Lepp,Matt Johnson,Michael Keenan,Michael Main,Michal Sramka,Naomi Shapiro,Nat Martin,Noah Aydin,Nisar Hundewale,Paul J. Kaiser,Paul Kube,Paulo Franca,Richard Borie,Scot Drysdale,Scott Strong,Sheila Foster,Steve Mahaney,Susanne Sherba,Thomas Judson,Walter A. Manrique,Wei Lian Chen和Wojciech Komornicki。
还要感谢用过本书前几版的许多老师,他们的建议相当有价值。最后感谢Kenrick Mock帮我实现了这一版的全部修订。他的工作令我和编辑激赏!
目 录
第1章 计算机和C++编程入门 11.1 计算机系统 2硬件 2软件 5高级语言 6编译器 7历史回顾 91.2 编程和问题求解 9算法 10程序设计 11面向对象编程 12软件生命周期 121.3 C++入门 13C++语言的起源 13一个C++示范程序 14陷阱:在\n中错误地使用斜杠 17编程提示:输入和输出语法 17简单C++程序的布局 17陷阱:在include的文件名前错误地添加一个空格 19编译和运行C++程序 19陷阱:编译C++11程序 19编程提示:让程序运行起来 201.4 测试和调试 22各种程序错误 22陷阱:错误地假定程序正确 23小结 24自测题答案 25编程练习 26编程项目 27第2章 C++基础知识 292.1 变量和赋值 30变量 30名称:标识符 32变量声明 33赋值语句 34陷阱:未初始化的变量 35编程提示:使用有意义的名称 362.2 输入和输出 37使用cout进行输出 37include预编译指令和命名空间 38转义序列 39编程提示:用\n或endl终止每一个程序 40格式化带小数点的数字 41用cin进行输入 42设计输入和输出 43编程提示:I/O中的换行 432.3 数据类型和表达式 44int类型和double类型 44其他数值类型 45C++11类型 46char类型 47bool类型 48string类简介 48类型的兼容性 49算术操作符和表达式 50陷阱:除法中的整数 52更多赋值语句 532.4 简单控制流程 54一个简单的分支机制 54陷阱:连续的不等式 58陷阱:该用==的时候用了= 58复合语句 59简单的循环机制 61递增操作符和递减操作符 63编程实例:信用卡余额 64陷阱:无限循环 652.5 程序风格 67缩进 67注释 67为常量命名 69小结 71自测题答案 72编程练习 75编程项目 76第3章 更多的控制流程 813.1 使用布尔表达式 82布尔表达式求值 82陷阱:将布尔表达式转换成int值 85枚举类型(选读) 873.2 多路分支 87嵌套语句 88编程提示:在嵌套语句中使用花括号 88多路if-else语句 90编程实例:州收入税 91switch语句 94陷阱:忘记在switch语句中添加break 96为菜单使用switch语句 97代码块 98陷阱:疏忽局部变量 1003.3 C++循环语句详解 101while语句回顾 101再论递增操作符和递减操作符 102for语句 104陷阱:for语句中多余的分号 108应该使用哪种循环 108陷阱:未初始化的变量和无限循环 110break语句 110陷阱:嵌套循环中的break语句 1113.4 设计循环 111求和与求乘积的循环 112终止循环 113嵌套循环 115调试循环 116小结 119自测题答案 120编程练习 123编程项目 124第4章 过程抽象和返回值的函数 1294.1 自顶向下设计 1304.2 预定义函数 130使用预定义函数 131随机数生成 134强制类型转换 135强制类型转换的古老形式 137陷阱:整数除法丢弃了小数部分 1374.3 程序员自定义函数 138函数定义 138返回布尔值的函数 142另一种形式的函数声明 142陷阱:实参顺序错误 143函数定义语法小结 144再论函数定义的位置 144编程提示:在分支语句中使用函数调用 1454.4 过程抽象 146黑盒的比喻 146编程提示:选择形参名称 147编程提示:嵌套循环 148案例分析:购买比萨 150编程提示:使用伪代码 1544.5 作用域和局部变量 155函数如同小程序 155编程实例:豌豆试验田 157全局常量和全局变量 157传值形参是局部变量 158块作用域 160再论命名空间 161编程实例:阶乘函数 1634.6 重载函数名称 164重载入门 164编程实例:购买比萨(修订版) 166自动类型转换 168小结 170自测题答案 171编程练习 173编程项目 174第5章 用函数完成所有子任务 1775.1 void函数 178void函数的定义 178编程实例温度换算 180void函数中的return语句 1815.2 传引用参数 182初探传引用调用 182传引用调用详解 184编程实例:swapValues函数 187混合的参数列表 188编程提示:应该使用哪种参数 189陷阱:疏忽造成的局部变量 1905.3 使用过程抽象 192在函数中调用其他函数 192前条件和后条件 193案例分析:超市定价系统 1945.4 测试和调试函数 198存根和驱动程序 1985.5 常规调试技术 201不抱成见 201检查常见错误 202定位错误 202assert宏 203小结 205自测题答案 206编程练习 208编程项目 209第6章 I/O流——对象和类入门 2136.1 流和基本文件I/O 214为什么要用文件来I/O 215文件I/O 215类与对象入门 218编程提示:检查文件是否成功打开 219文件I/O技术 222追加到文件(选读) 223文件名作为输入(选读) 2256.2 流I/O工具 227用流函数格式化输出 227操纵元 230流作为函数实参 232编程提示:检查文件尾 233命名空间的问题 234编程实例:整理文件格式 2356.3 字符I/O 236get和put成员函数 236putback成员函数(选读) 239编程实例:检查输入 239陷阱:输入中不期而遇的'\n' 241编程实例:另一个newLine函数 242函数的默认实参(选读) 243eof成员函数 246编程实例:编辑文本文件 247预定义字符函数 249陷阱:toupper和tolower返回值 250小结 252自测题答案 253编程练习 257编程项目 258第7章 数组 2637.1 数组入门 264声明和引用数组 264编程提示:为数组使用for循环 266陷阱:数组索引总是从零开始 266编程提示:为数组长度使用已定义常量 266数组在内存中的表示 267陷阱:数组索引越界 268初始化数组 269编程提示:C++11基于范围的for语句 2707.2 函数中的数组 272索引变量作为函数参数 272整个数组作为函数参数 274const参数修饰符 276陷阱:const参数修饰符的使用不一致 277返回数组的函数 278案例分析:产量图 2787.3 数组编程 287部分填充数组 287编程提示:不要吝啬形参 289编程实例:搜索数组 290编程实例:数组排序 291编程实例:冒泡排序 2947.4 多维数组 297多维数组基础 297多维数组参数 298编程实例:二维打分程序 299陷阱:在数组索引之间使用逗号 302小结 303自测题答案 304编程练习 306编程项目 307第8章 字符串和向量 3158.1 字符串的数组类型 316C字符串值和C字符串变量 317陷阱:为C字符串使用=和== 319<cstring>中的其他函数 321陷阱:使用strcpy复制C字符串越界 322C字符串输入和输出 324C字符串到数值的转换和可靠输入 3268.2 标准string类 330标准类string简介 330string类的I/O 332编程提示:getline的其他版本 334陷阱:混合使用cin>>变量;和getline 335用string类进行字符串处理 336编程实例:回文测试 338string对象和C字符串之间的转换 341字符串和数字之间的转换 3428.3 向量 342向量基础知识 342陷阱:使用方括号时超出向量长度 345编程提示:向量赋值具有良好行为 345效率问题 345小结 347自测题答案 348编程练习 349编程项目 350第9章 指针和动态数组 3559.1 指针 356指针变量 357基本内存管理 362陷阱:虚悬指针 362静态变量和自动变量 362编程提示:定义指针类型 3639.2 动态数组 364数组变量和指针变量 365创建和使用动态数组 366指针运算(选读) 370多维动态数组(选读) 371小结 373自测题答案 374编程练习 374编程项目 375第10章 定义类 37910.1 结构 380用于异种数据的结构 380陷阱:结构定义中忘记添加分号 383结构作为函数参数 384编程提示:使用层次化结构 384对结构进行初始化 38610.2 类 388定义类和成员函数 388公共成员和私有成员 391编程提示:将所有成员变量设为私有 396编程提示:定义取值函数和赋值函数 397编程提示:将赋值操作符用于对象 398编程实例:BankAccount类(版本1) 398总结类的一些特征 402用于初始化的构造函数 403编程提示:总是包括默认构造函数 408陷阱:无参构造函数 409C++11的成员初始化器和构造函数委托 41010.3 抽象数据类型 411用于生成抽象数据类型的类 412编程实例:类的另一种实现 41410.4 继承 418派生类 418定义派生类 419小结 423自测题答案 424编程练习 428编程项目 428第11章 类中的友元函数、重载操作符和数组 43311.1 友元函数 434编程实例:一个相等性函数 434友元函数 436编程提示:定义取值函数和友元函数 438编程提示:同时使用成员函数和非成员函数 439编程实例:Money类(版本1) 439实现digitToInt(选读) 443陷阱:数字常量中的前置零 444const参数修饰符 445陷阱:修饰符const的用法不一致 44711.2 重载操作符 449重载操作符 449用于自动类型转换的构造函数 452重载一元操作符 453重载>>和<< 45411.3 数组和类 460类数组 460数组作为类成员 463编程实例:用于部分填充数组的类 46311.4 类和动态数组 465编程实例:字符串变量类 466析构函数 468陷阱:指针作为传值参数 469拷贝构造函数 471重载赋值操作符 474小结 477自测题答案 478编程练习 484编程项目 484第12章 独立编译和命名空间 49112.1 独立编译 492ADT回顾 492案例分析:独立编译的DigitalTime类 493使用#ifndef 500编程提示:定义其他库 50212.2 命名空间 503命名空间和using预编译指令 503创建命名空间 504限定名称 506命名空间的微妙之处(选读) 507无名命名空间 508陷阱:混淆全局命名空间和无名命名空间 512小结 513自测题答案 514编程练习 515编程项目 516第13章 指针和链表 51713.1 节点和链表 518节点 519nullptr 521链表 522在表头插入节点 523陷阱:丢失节点 525搜索链表 526指针作为迭代器 528在列表中插入和删除节点 528陷阱:为动态数据结构使用赋值操作符 531链表的变体 531类构成的链表 53313.2 栈和队列 536栈 536编程实例:栈类 536队列 539编程实例:队列类 540小结 544自测题答案 545编程练习 546编程项目 547第14章 递归 55314.1 面向任务的递归函数 554案例分析:垂直数字 555深入递归 559陷阱:无穷递归 560用于递归的栈 562陷阱:栈溢出 563递归与迭代 56314.2 面向值的递归函数 564要返回值的递归函数的常规形式 564编程实例:另一个求乘方函数 56414.3 递归思想 567递归设计技术 567案例分析:二叉搜索(递归思想示例) 569编程实例:递归成员函数 574小结 577自测题答案 578编程练习 581编程项目 581第15章 继承 58515.1 继承基础 586派生类 588派生类中的构造函数 593陷阱:使用来自基类的私有成员变量 595陷阱:私有成员函数不会继承 596protected限定符 596重定义成员函数 598重定义与重载的比较 600访问重定义的基函数 60115.2 继承细节 602不继承的函数 602派生类中的赋值操作符和拷贝构造函数 602派生类中的析构函数 60315.3 多态性 604晚期绑定 604C++虚函数 605虚函数和扩展类型兼容性 609陷阱:不使用虚成员函数 612陷阱:试图对虚成员函数定义不齐全的类进行编译 612编程提示:使析构函数成为虚函数 613小结 615自测题答案 616编程练习 619编程项目 620第16章 异常处理 62716.1 异常处理基础 628异常处理的简单例子 629定义自己的异常类 635多个throw块和catch块 636陷阱:首先捕捉较具体的异常 638编程提示:异常类可能很简单 638在函数中抛出异常 639异常规范 640陷阱:派生类中的异常规范 64116.2 用于异常处理的编程技术 642抛出异常的时机 642陷阱:未捕捉的异常 643陷阱:嵌套try-catch块 643陷阱:滥用异常 644异常类层次结构 644测试可用内存 644重新抛出异常 645小结 646自测题答案 647编程练习 647编程项目 649第17章 模板 65117.1 用于算法抽象的模板 652函数模板 653陷阱:编译器的复杂性 656编程实例:泛型排序函数 657编程提示:如何定义模板 660陷阱:为不恰当的类型使用模板 66017.2 用于数据抽象的模板 660类模板的语法 660编程实例:数组类 663小结 668自测题答案 669编程练习 671编程项目 671第18章 标准模板库 67518.1 迭代器 676using声明 677迭代器基础 677编程提示:使用auto简化变量声明 681陷阱:编译器问题 681迭代器的种类 682常量和可变迭代器 684逆向迭代器 685其他种类的迭代器 68718.2 容器 687顺序容器 687陷阱:迭代器和删除元素 690编程提示:容器中的类型定义 691容器配接器stack和queue 691关联容器set和map 693编程提示:为容器使用初始化、基于范围的for和auto 698效率问题 69918.3 泛型算法 699运行时间和大O表示法 700容器访问运行时间 703不修改容器的算法 703会修改容器的算法 706set算法 707排序算法 70818.4 不断进化的C++ 708std::array 709正则表达式 710线程 713智能指针 717小结 722自测题答案 723编程练习 724编程项目 724附录A C++关键字 729附录B 操作符的优先级 730附录C ASCII字符集 731附录D 部分库函数 732附录E 内联函数 736附录F 重载数组索引方括号 737附录G this指针 738附录H 将操作符重载为成员操作符 740