描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787302498544
目录
第1章Visual C 集成开发环境1
1.1Visual C 概述1
1.1.1Visual C 的特点1
1.1.2集成开发环境窗口2
1.1.3编译器和链接器5
1.1.4编写Win32控制台应用程序5
1.1.5MSDN帮助系统7
1.2项目和项目工作区8
1.2.1项目8
1.2.2项目工作区9
1.2.3ClassView类视图9
1.2.4ResourceView资源视图10
1.2.5FileView文件视图11
1.2.6项目设置11
1.3编辑器12
1.3.1源代码编辑器12
1.3.2资源编辑器13
1.4菜单栏和工具栏18
1.4.1菜单栏18
1.4.2工具栏20
习题23第2章C 语言基础25
2.1C 概述252.1.1C 语言的历史和特点25
2.1.2C 程序与C程序26
2.1.3C 对C的一般扩充28
2.2C 程序基本要素29
2.2.1标识符和关键字29
2.2.2常量和变量30
2.2.3运算符和表达式30
2.3C 数据类型32
2.3.1基本数据类型32
2.3.2数组33
2.3.3指针35
2.3.4字符串37
2.3.5const常量类型39
2.3.6结构体41
2.3.7枚举44
2.3.8typedef类型定义44
2.4控制语句45
2.4.1选择语句45
2.4.2循环语句48
2.4.3转移语句51
2.5函数52
2.5.1函数的定义52
2.5.2函数的调用和参数传递53
2.5.3函数的声明56
2.5.4内联函数57
2.5.5函数的默认参数值57
2.5.6引用58
2.6作用域与存储类型61
2.6.1变量的作用域61
2.6.2变量的存储类型63
2.6.3作用域限定符66
2.6.4命名空间66
2.6.5函数的存储类型70
2.6.6动态内存分配71
2.7编译预处理指令73
2.7.1#define宏定义指令73
2.7.2#include文件包含指令74
2.7.3条件编译指令75
习题77第3章类和对象87
3.1面向对象程序设计方法及特征87
3.1.1结构化程序设计87
3.1.2面向对象程序设计88
3.1.3面向对象程序设计的基本特征90
3.2C 类93
3.2.1类的定义与实现93
3.2.2构造函数和析构函数95
3.2.3拷贝构造函数97
3.2.4this指针100
3.3静态成员102
3.3.1静态数据成员102
3.3.2静态成员函数104
3.4组合类106
3.4.1组合类的定义106
3.4.2组合类的拷贝构造函数109
3.5友元110
3.5.1友元函数110
3.5.2友元类112
3.6常对象和常对象成员113
3.6.1常对象113
3.6.2常成员函数114
3.6.3常数据成员115
习题115第4章继承与多态123
4.1继承与派生123
4.1.1基类和派生类123
4.1.2派生类的构造函数和析构函数128
4.1.3多继承130
4.1.4虚基类133
4.2多态和虚函数138
4.2.1基类指针指向派生类对象138
4.2.2虚函数140
4.2.3虚析构函数142
4.2.4纯虚函数与抽象类143
4.3重载145
4.3.1函数重载145
4.3.2运算符重载148
4.4模板154
4.4.1函数模板154
4.4.2类模板156
4.5Microsoft Visual C 的语法扩充158
4.5.1Visual C 扩充定义的数据类型158
4.5.2Visual C 运行库159
4.5.3运行时类型识别161
4.5.4编程规范163
习题164第5章创建应用程序框架173
5.1应用程序向导173
5.1.1Visual C 向导的类型173
5.1.2MFC AppWizard的使用步骤174
5.1.3MFC应用程序的开发流程184
5.2应用程序向导生成的文件186
5.2.1应用程序向导生成的文件类型186
5.2.2应用程序向导生成的头文件187
5.2.3应用程序向导生成的源文件189
5.2.4应用程序向导生成的资源文件195
5.2.5应用程序向导生成的其他文件196
5.3ClassWizard类向导198
5.3.1ClassWizard的功能198
5.3.2添加消息处理函数199
5.3.3添加类201
5.4程序调试203
5.4.1查找源程序中的语法错误203
5.4.2Debug调试器204
5.4.3跟踪调试程序206
习题209第6章文档与视图213
6.1文档/视图结构213
6.1.1文档/视图结构概述213
6.1.2文档与视图之间的相互作用215
6.1.3多文档217
6.2菜单设计220
6.2.1建立菜单资源220
6.2.2添加菜单命令处理函数222
6.2.3弹出式菜单226
6.3鼠标消息处理228
6.3.1鼠标消息228
6.3.2一个简单的绘图程序228
6.4工具栏和状态栏设计234
6.4.1添加工具栏按钮234
6.4.2定制状态栏235
6.5文档的读写238
6.5.1使用CFile类238
6.5.2序列化240
6.5.3自定义类的序列化242
6.6滚动视图和多视图245
6.6.1滚动视图245
6.6.2多视图247
习题251第7章对话框和控件255
7.1对话框概述255
7.1.1基于对话框的应用程序255
7.1.2对话框类CDialog257
7.1.3信息对话框258
7.2使用对话框260
7.2.1一般对话框工作流程260
7.2.2创建对话框262
7.2.3添加控件及关联的成员变量264
7.2.4对话框数据交换(DDX)和校验(DDV)270
7.3标准控件272
7.3.1控件概述272
7.3.2组织控件274
7.3.3控件的共有属性275
7.3.4静态控件277
7.3.5编辑框278
7.3.6按钮281
7.3.7列表框284
7.4公共控件289
7.4.1旋转按钮290
7.4.2滑块292
7.4.3进度条295
7.4.4标签297
习题302第8章MFC原理与方法307
8.1Windows编程基础307
8.1.1Windows编程特点307
8.1.2应用程序编程接口(API)308
8.1.3Windows消息314
8.1.4句柄316
8.2微软基础类(MFC)317
8.2.1MFC概述318
8.2.2MFC体系结构319
8.2.3学习MFC的方法321
8.3MFC应用程序框架322
8.3.1应用程序框架中的对象322
8.3.2MFC应用程序的生存与消亡323
8.3.3常用的MFC文件326
8.4MFC消息管理329
8.4.1MFC消息映射机制329
8.4.2消息的发送331
8.4.3自定义消息处理332
8.5MFC宏335
8.5.1常用的MFC宏336
8.5.2运行时类型识别和动态创建337
8.5.3MFC调试宏339
习题340第9章图形绘制345
9.1图形设备接口345
9.1.1概述345
9.1.2设备环境346
9.1.3GDI坐标系和映射模式348
9.1.4颜色的设置354
9.2画笔和画刷355
9.2.1GDI对象355
9.2.2使用画笔356
9.2.3使用画刷360
9.2.4使用GDI堆对象361
9.2.5基本几何图形的绘制363
9.3文本与字体365
9.3.1绘制文本365
9.3.2字体概述367
9.3.3创建字体368
习题373第10章Visual C 编程深入377
10.1异常处理377
10.1.1C 异常处理377
10.1.2Win32异常处理380
10.1.3MFC异常宏和异常类383
10.1.4MFC异常处理385
10.2动态链接库388
10.2.1动态链接库概述388
10.2.2创建动态链接库389
10.2.3使用动态链接库392
10.3非模态对话框395
10.3.1模态对话框与非模态对话框395
10.3.2非模态对话框工作流程395
习题400常用术语索引403参考文献407
第4版前言移动互联、人工智能、大数据和云计算为计算机科学与技术的发展带来了持续的动力,高等学校计算机类专业的发展进入新的阶段。C、C 和Java等编程语言已经群雄逐鹿多年,如今Python、Ruby、HTML 5等编程语言开始崭露头角。但是,不管编程语言如何推陈出新,面向对象程序设计的方法至今没有发生实质性改变,且日臻完美。社会发展日新月异,对人才的要求不断提高。程序设计类课程是高等学校计算机类专业的核心课程,该课程的教学质量也列入工程教育专业认证的重要指标,掌握面向对象程序设计技术是对计算机类专业毕业生最基本的要求。本书第1版被评为“北京高等教育精品教材”,第2版被评为普通高等教育“十一五”国家级规划教材。本书第3版出版后受到了更多教师、学生和其他读者的欢迎,很多同行和读者提出了一些建设性意见。为了适应当前程序设计类课程的教学改革,我们结合近几年的教学和实践体会,对教材进行了修订改编。本书第4版进一步精选内容,突出重点和要点,兼顾广大学生的学习特点,以适应不同课程、不同专业的教学需要。本书第4版共分为10章,第1章介绍Visual C 集成开发环境,第2章介绍C 语言基础知识,第3章介绍C 程序设计中的类和对象,第4章介绍继承与多态的编程方法,第5章介绍MFC应用程序框架,第6章介绍MFC文档与视图,第7章介绍Visual C 对话框和控件编程,第8章介绍MFC原理与方法,第9章介绍图形绘制方法,第10章介绍异常处理、动态链接库等高级编程方法。一些老师参加了本书第4版的修订工作,刘晓晓修订了第2、3章,骆曦修订了第4章,李冬云修订了第5章,张敬尊修订了第6章,刘治国修订了第8章,刘振恒修订了第9章。王育坚修订了第1、7、10章,并负责全书的组稿和定稿。王骁参加了程序调试工作。很多高校教师和学生对本书的再版提出了宝贵的意见和建议,对作者给予了莫大的鼓励,在此一并表示感谢。因作者水平有限,书中难免存在疏漏,敬请广大读者批评指正。
王育坚2018年1月
第3版前言面向对象的方法日趋完善,其倡导的封装性、继承性和多态性等特性在应用中不断被人们所领悟,并得以提升和推广。在有了Java和.NET的时代,尽管新的编程技术和工具不断涌现,但无论程序设计技术如何发展,面向对象程序设计方法仍是当前编程技术的根本和基础,以MFC为主的Visual C 在桌面应用程序开发方面仍然具有很大的优势。本书的第1版被评为“北京高等教育精品教材”,第2版被评为普通高等教育“十一五”国家级规划教材。面向对象程序设计类课程是计算机科学与技术学科的专业基础课,也是其他电类专业的选修课。本书自2003年出版以来,受到了广大教师、学生和其他读者的欢迎,被很多开设相关课程的学校采用。自本书第2版出版以来的近6年中,教学方法和内容的改革不断深入,很多同行和读者提出了一些建设性意见,并指出了书中存在的一些问题。为了适应当前程序设计类课程的教学需要,我们认真听取了读者的意见,对《Visual C 面向对象编程教程》进行了修订,更名为《Visual C 面向对象编程(第3版)》。在进行第3版的修订时,我们仍然遵循第1版和第2版的编写原则,继续体现简明与实用的特点,从面向实际应用的教学定位出发。在内容选择上,进一步精选,突出重点和要点,并补充了一些新的内容。与第2版相比,第3版修正了差错,叙述也更准确,尽力避免歧义和疏漏,提高了教材的可读性。在内容的广度和深度上兼顾广大学生的学习特点,以适应不同课程、不同专业的教学需要。力求使不同专业的学生通过课程的学习,能够掌握Visual C 面向对象编程的方法。本书按照C 程序设计、Visual C 编程基础和Visual C 高级编程3个框架组织内容。作者认真分析了国内外同类教材的特点,并结合多年来授课的经验,进一步完善了第一部分的内容,重点改写了第2、3、4章,加大了C 程序设计的内容。此外,对第二部分和第三部分进行了修订,并精简了第11章的内容和应用实例,以压缩教材的篇幅。对教材中的部分例题和习题也进行了改编,增强了教材的实用性。为配合教学,拟编写配套的习题解析和实验指导书。近年来,虽然Microsoft公司针对Visual C 不断推出新版本,但从教学的角度来看,其编程原理和方法没有根本改变,它们是完全兼容的。因此,本书仍然以Visual C 6.0为教学平台,读者在学习时应以掌握Visual C 面向对象编程的基本原理与应用方法为主。对不同开发工具的使用,可根据需要查阅其帮助文档或者一些工具参考书。本书得到了很多教师的指导和帮助,张睿哲、刘治国、刘畅、王郁昕、刘宏哲、黄静华、袁家政、王骁等参加了第3版的编写和程序调试工作。很多同仁和读者对本书的再版提出了意见和建议,对作者给予了莫大的鼓励。本次再版也得到了清华大学出版社的支持,在此一并表示诚挚的感谢。由于作者水平有限,书中难免存在一些疏漏和不当之处,敬请同行和各位读者批评指正,并欢迎来信共同探讨相关问题。
王育坚[email protected]: //www.51Labor.cn2013年8月
第2版序随着知识化和信息化新经济时代的到来,作为信息技术龙头的计算机及软件技术突飞猛进,呈现出平台网络化、方法对象化、系统构件化、开发工程化、过程规范化的发展趋势,信息技术的应用与专业领域的结合更加紧密。为了培养和造就高素质的计算机应用人才,以满足社会的需求,我们需要深入进行教学改革。从目前情况看,高校计算机教学的改革仍落后于计算机及软件技术的发展,课程内容仍然只偏重理论知识的讲授,而忽视实践能力的培养,学生毕业后难以适应实际工作。计算机的许多课程实践性极强,不动手是学不会的。程序设计课的主要任务是培养学生的编程能力。编程需要掌握基本理论和基本方法,更为重要的是能够利用人类通用智力工具去解决实际问题,因此编程能力的培养必须强化动手实践。通过实践培养计算思维能力,养成良好的编程习惯;通过实践学会如何调试程序,如何优化程序代码,如何对程序的运行结果进行分析,如何提高程序的规范性和可读性。科学和艺术是相通的。编程是技术,也是艺术,给编程者留有较大的发挥创造性的空间。优化的程序代码中凝聚着理性思维之美、算法艺术之妙,使编程者在付出艰辛的努力之后,会获得成就感,增强自信心。当今,国内许多高等院校的相关专业开设了C 程序设计课程,不少院校的教学内容偏重于一般的C 程序设计方法,没有强调如何结合Visual C 开发环境进行Windows应用程序的开发,去解决各类实际问题,而实际上这一点对于计算机专业的学生来说尤为重要。本书作者王育坚老师认真分析了高校程序设计课程的现状和发展趋势,对编程理论和技术进行了深入的研究,参阅了大量的Visual C 编程教材和文献资料,在第1版的基础上完成了这本《Visual C 面向对象编程教程》。作者长期从事程序设计课程教学和软件研发工作,能够将教材内容与当今编程技术紧密结合,提高了教材的实用性。全书教学内容设计合理,涵盖了C 、Visual C 、MFC和Windows编程内容,既有原理性的讲解,也有实例说明和分步骤的编程实现,深入浅出地引导读者思维和实践,注重培养学生实际的应用软件开发能力。本书适合作为Visual C 程序设计类课程的教材或教学参考书,对Visual C 应用开发人员也大有裨益。计算机应用正沿着硬件和软件两条主线相互促进,不断发展。如果说硬件是计算机的躯体,那么软件就是计算机的灵魂,软件的地位举足轻重。软件和信息服务业将成为世界第一大产业,中国软件业能否赶上国际水平,关键在于是否拥有一大批不同层次的高素质的软件人才。相信有志于中国软件业的读者阅读本书后会有所收获。
全国高等院校计算机基础教育研究会副理事长清华大学计算机科学与技术系教授、博士生导师吴文虎北京·清华园2007年7月
第2版前言软件技术发展的一个主要体现是程序设计方法的不断改进。如今我们正处于程序设计方法的变革之中,从结构化程序设计到面向对象程序设计,再到基于组件程序设计。面向对象语言不断推出,从最早的Smalltalk到目前广泛使用的C 和Java,再到Microsoft公司推出的C#。作为C语言继承者的C 语言仍然是目前应用最广泛的面向对象程序设计语言,而Visual C 是使用人数最多的C 编程工具。程序设计是计算机专业或其他信息类专业学生的一项基本技能。随着程序设计技术的不断发展,社会对软件人才的要求也越来越高。工欲善其事,必先利其器,要想成为一个高水平的程序员,需要在以下4个方面进行认真的学习:算法设计与分析、程序设计语言、程序设计方法学和程序设计环境与工具。基于这4个方面的需要,高校都开设了相关的课程,如很多高校的计算机及相关专业都开设了“Visual C 程序设计”课程。本书第1版自2003年出版以来,得到了教师、学生和其他读者的广泛认同,先后重印了9次,并被很多高校作为教材或教学参考书使用。本书第1版的出版时间已过去近4年,从服务教学、服务读者的角度考虑,教材内容应该跟上技术发展的步伐。就作者本人感受,第1版还有不少不甚满意之处,有些内容不太实用,编排上也不尽合理,学习时会产生一些理解上的障碍。很多教师和学生也通过Email与作者进行交流,提出了改进意见和建议。这些都促使作者在两年前就着手编写本书的第2版。根据作者的教学经验和读者建议,第2版保留了第1版的基本风格、基本框架和基本内容,一般还是首先进行原理性的介绍,然后通过实例来讲解技术细节。全书共10章。与第1版相比,第2版在大的方面做了如下改动:重写了第2章和第3章,考虑到很多高校将本书作为面向对象程序设计课程的教材,加大了第3章C 面向对象程序设计的份量;为了有利于教学,将原第7章分成了两章(即第6章和第9章);删去了原第9章中不实用的内容。在具体细节方面,对第1版所有文字内容进行了改写,力求叙述更加准确,更加符合学习的特点和教学的要求。读者仔细阅读第2版后可以体会到其中的任何改变都经过了作者的深思熟虑和认真推敲。Visual C 是基于Windows的可视化开发环境,同时还提供了一些C 类库,其中最重要的是MFC。随着技术的发展,MFC已不是Visual C 中唯一的类库,其他的还有ATL、STL等。Microsoft公司还推出了Visual C .NET,但考虑作为专业基础课教材,重点是介绍程序设计技术,而不是讲解具体的开发环境,因此第2版仍然以Visual C 6.0作为开发环境。Visual C 程序设计内容广泛,本书包含了C 、Visual C 、MFC和Windows编程内容,很多学生反映学习难度大,学时数不够,教师可以根据具体情况和学时数合理取舍内容,提出不同的教学要求。例如,如果学生没有C 基础,可以将教学重点放在前6章。如果已开设过C 程序设计课程,可以将教学重点放在第1章、第4~8章。限于篇幅,对于较复杂的技术(如第10章内容),本书只进行了基本的介绍,如果读者希望进行深入的研究,需要查阅MSDN Library或其他参考文献。清华大学吴文虎教授阅读了本书,并为本书作序。鲍有文教授也对本书提出了修改意见。参加第2版编写和程序调试工作的还有张睿哲、刘治国、刘畅、王郁昕、刘宏哲、黄静华、袁家政。本书再版过程中,清华大学出版社给予了很大的帮助,在此一并表示衷心的感谢!由于计算机及软件技术发展很快,加之作者水平有限,书中难免有不足和疏漏之处,希望广大读者与同行不吝赐教。
王育坚[email protected]://www.51Labor.com2007年6月
第1版序我一直对程序库/框架(libraries/frameworks)之类的产品和技术有着深厚的兴趣。在我的技术探索地图中,程序库/框架一直是最大的板块。MFC(Microsoft Foundation Classes),这个曾经最重要、最为全世界广泛使用的先驱框架产品之一,一直是我关注的焦点。由于MFC附含于Microsoft Visual C 之中,导致我们常把学习MFC和学习Visual C 并谈。名称其实无所谓,学习Visual C 主要就是学习如何运用MFC。Visual C 本身只是个编译器,并不需要太多学习(当然它丰富的集成环境需要多加熟练,但这种学习很简单)。这里真正要学习的是C 语言,以及以C 语言写就的庞大复杂的应用框架MFC。所谓框架,是一种以classes集体力量为用户完成工作,并允许用户在特定协议下注入新血完成扩张的大型程序库。个别class有自己明确的目标,集体行动的classes当然也必须有一致的明确目标,因此各式各样的框架有聚焦于数据结构/算法者(如STL),有聚焦于网络通信者(如ACE),有聚焦于设计模式者(如Loki)。其中,聚焦于应用程序骨干者(通常包含GUI、文档视图、打印、预视、数据交换能力……)技术位阶极高,我们特别称为应用框架(application framework)。MFC就是一种“应用框架”,帮助你模塑、建构自己的Windows应用程序骨干。除非我们是框架开发者或研究者,或者是为了学术目的与纯粹技术钻研,否则学习框架只是为了应用,不是为了其中展现的技术,更不是为了摸清楚其中每一个环节和每一个流动。但是,正因为我们对事物的运用娴熟度随着我们对事物原理的更多理解而增强,又因为MFC如此庞大繁复(框架无不如此),管中窥豹、盲人摸象的情况时有所闻,失控失准的现实例子屡见不鲜,所以才需要Dissecting MFC、Internal MFC之类的书籍,由它们以各自的定位为读者进行一场外科手术,剖析MFC的肌理与神经。为了流畅地运用MFC框架,我们还需要大量的实例和良好的解说,并且最好能够与MFC的肌理和神经关联起来。这方面,在MFC问世多年的今天,有了很多好书,例如Inside Visual C 和Programming Windows with MFC。王育坚老师以十分认真严谨的态度,完成了《Visual C 面向对象编程教程》的编写工作。我结识王育坚老师于网络虚拟空间,迄今未曾见面,却很荣幸有机会在本书出版之前阅读定稿。从这些原稿中,我体会到本书在选题、内容上的优越,以及作者的认真、用心与自信。任何技术都有明日黄花的一天,MFC也不可能例外,但是从一本优秀书籍中所学到的技术、知识乃至态度,是可以延续的。中国的信息产业教育非常需要坚实并富有实际作用的教材。这需要一批对技术、对教育、对写作都有足够实力与热情的人参与,也需要出版大环境提供更优渥的吸引力。技术书籍谈的是技术,技术书籍的写作本身就是一门极不容易的技术。基于我对本书原稿的印象以及对王育坚老师的认识,我很乐意向读者推荐本书。
侯捷中国台湾·新竹http://www.jjhou.com
第1版前言当本书准备交付出版社之际,编写过程中的烦躁和劳累全被拂去。我以前曾写过书,深知写书过程中的痛苦。因此,当着手写这本书时,面对Visual C 类书籍汗牛充栋的局面,真有些惶惶不安。甚至在正式动笔撰稿时,还有过放弃的念头,但我最终坚持下来了。近两年的辛勤耕耘,最终瓜熟蒂落。就像中国台湾Windows编程著作家和专栏评论家侯捷先生在《深入浅出MFC》一书中所说,“学习过往的艰辛,模糊而明亮,是学成冠冕上闪亮的宝石。过程愈艰辛,宝石愈璀璨。”艰辛永远是与幸福愉悦相伴相随的。本书是根据北京高等教育精品教材建设项目的要求而编写的,目的是为相关课程的教学提供一本教材或参考书。毋庸置疑,高等教育改革的一个重要方向就是使教学真正面向社会需要。作者有一个深刻的感受,就是当前大学计算机课程的教学落后于计算机技术的飞速发展,知识的讲授仍然停留在理论基础上,培养的人才无法较快地适应实际的软件开发工作。教学实践证明,Visual C 作为一个应用非常广泛的Windows程序开发工具,在高校相关专业开设其编程课程是必要且有效的。市面上介绍Visual C 的书籍很多,但要真正找到适合大学专业课程教学的教材却不易。本书的特色是:读者如果真正读懂了本书,就能够成为一名合格的Visual C 程序员,因为本书浓缩了作者多年来软件开发和教学实践的经验和体会。作者通过多次讲授Visual C 编程,能够深刻理解Visual C 编程的基本学习要求。本书主要面向Visual C 的初、中级用户,读者阅读本书前最好具有C语言基础。比较Visual Basic、C Builder和Delphi等编程工具,用Visual C 编写Windows应用程序最富于挑战性和艰巨性。有些人学习了很长时间也只能长期在Visual C 的门口徘徊,究其根源,是由于他们采取一种蜻蜓点水的学习方式,而没有系统地学习。要想在使用Visual C 编程时游刃有余,在学习过程中必须解决所面临的4个主要困难:C 语言的面向对象机制、MFC类库功能的庞大、Windows编程的复杂性以及向导所建立的应用程序框架的透明性。Visual C 编程的内容广泛并相互交织,如何编排见仁见智。本书在编写过程中充分考虑了Visual C 的学习特点和教学过程中的基本思路,将重点放在Visual C 基础和实用的知识点上,力求让读者按照一个循序渐进的过程来学习,提高学习效率。为了突出教学重点,对书中用到的实例进行了一些简化,这样既节约了篇幅,又避免了喧宾夺主。区别于一般的技术读物,本书提供的习题非常丰富,并且都是围绕书中例题而展开的,使读者能够马上学有所用。如果将本书作为教材使用,可将课程的教学分为课堂讲授、教师指导上机和学生课余上机3个层次。课堂讲授和教师指导上机的教学课时为72~90学时,教师可根据不同教学对象或教学大纲的要求安排学时数和教学内容。上机编程是本课程的重要环节,建议教师指导学生上机的课时为每周2学时。此外,学生必须花大量时间自己上机,一般学生课余自己上机的时间不少于每周3学时。每章习题中都提供了专门用于上机的习题,教师可根据具体情况酌情选择。本书凝聚了很多同仁的劳动和智慧,李启隆、宋一中、陈贻昆和王琦等老师参加了部分章节的编写,中国台湾的侯捷先生仔细阅读了本书,并义务为本书作序。在此,对他们表示衷心的感谢!感谢阅读本书的读者!感谢将本书作为教材的老师!恳请读者惠予批评指正。
王育坚[email protected]://www.51Labor.com2003年7月
第章
3第3章类和对象与C语言相比,C 语言的最大特点是引入了类的机制,并全面支持面向对象程序设计(Object Oriented Programming,OOP)。类和对象是面向对象程序设计方法中两个重要的基本概念。本章主要介绍面向对象程序设计的基本概念和C 面向对象程序设计的基本方法,包括C 类和对象、构造函数和析构函数、静态成员等内容。通过本章的学习,完成从C 结构化程序设计向C 面向对象程序设计的过渡。3.1面向对象程序设计方法及特征面向对象不只是一种程序设计方法,而是一种建立客观事物模型、分析复杂事物的思想方法,是以人们通常描述现实世界的方法来描述要解决的问题。面向对象程序设计是目前成熟并流行的软件开发技术,是面向对象的思想方法在程序设计上的体现。面向对象程序设计是对结构化程序设计(Structured Programming,SP)的继承和发展,既吸收了结构化程序设计的优点,又最大程度地解决了软件代码的重用和维护问题。3.1.1结构化程序设计20世纪60年代,随着计算机应用领域不断扩大和所处理的问题日益复杂,软件的规模越来越大,复杂程度越来越高,软件可靠性问题也越来越突出,软件危机开始爆发。所谓软件危机是指落后的软件生产方式无法满足迅速增长的软件需求,从而导致软件开发与维护过程中出现一系列严重问题。为了改变软件生产方式,提高软件生产率,人们提出了软件工程的概念,并开始重视程序设计方法的研究。20世纪70年代,结构化程序设计方法逐渐产生和形成。结构化程序设计是一种自顶而下、逐步求精的模块化程序设计方法。其基本思路是: 当解决一个复杂问题时,首先将复杂问题按功能划分为若干个模块,并且,若模块要完成的功能仍然较复杂,再将模块按功能进一步划分为若干个子模块,这样逐步细化,直到子模块的功能可以用一个子程序实现为止。采用这种模块化程序设计方法,由于各模块之间的关系简单,在功能上相对独立,因此程序易于分工编写,并且编写出来的程序结构清晰、可读性好。结构化程序设计是一种传统的面向过程程序设计(Procedure Oriented Programming,POP)的方法,即将解决一个问题看作设计出一个解决该问题的处理过程。著名的计算机科学家N. Wirth在20世纪70年代曾经提出一个公式: 算法 数据结构=程序这个公式揭示了程序的本质,即结构化程序设计就是定义数据和设计算法。定义数据就是选择合适的数据结构,设计算法就是根据所选择的数据结构设计解决问题的过程(函数),过程是对数据的操作。结构化程序设计按照工程的标准和规范将要设计的系统分解为若干功能模块,系统是实现模块功能的子程序的集合。从历史上看,与以前的非结构化程序相比,结构化程序在调试、可读性和可维护性等方面都有很大的改进,当时确实大大地促进了软件的发展。但是,以过程为中心设计系统并编写程序,每一次更新系统,除了一些接口简单的标准函数,大部分程序代码都必须重新编写,不能实现代码的可重用。结构化程序设计将系统分解为若干个功能模块,由于软、硬件技术的不断发展和用户需求的变化,按照系统功能划分的模块的设计要求容易发生变化,从而增加了系统维护的工作量。并且,结构化程序设计中数据和过程是分离的,若对某一数据结构做了修改,为了保证与数据的一致性,所有处理数据的过程(代码)都必须重新修改,这样就增加了软件设计的工作量,同时也加大了出错的概率。特别是随着问题复杂度的提高,软件规模会急剧增大,更是大大增加了软件的维护成本。3.1.2面向对象程序设计虽然结构化程序设计具有很多优点,但从本质上看,结构化程序设计是面向过程或操作的,不能直接反映人们解决问题的思路,很可能产生问题空间与方法空间在结构上的不一致。为了克服面向过程模式的固有缺陷,20世纪80年代提出了面向对象程序设计方法。面向对象程序设计是软件工程、结构化程序设计、数据抽象、信息隐藏、知识表示及并行处理等多种理论的积累与发展。按照面向对象的观点,客观世界是由各种各样的事物即“对象”(object)组成的,包括有形的对象和无形的对象。对象可以是人们要进行研究的任何事物,包括具体的对象和抽象的对象,不仅能表示具体的人、学生、猫、动物、汽车、计算机、程序、直线和数据库等,还能表示抽象的思想、规则、计划和事件等。每一类对象都有自己特定的属性(attribute)(如大小、形状和重量等)和行为(behavior)(如生长、行走、转弯、运算等),人们通过对象的属性和行为来认识对象。对象的属性用数据值来描述;对象的行为又称方法(method),用函数来定义。从世界观的角度看,面向对象的基本哲学认为世界是由各种各样具有自己的运动规律和内部状态的对象所组成的,不同对象之间的相互作用构成了完整的现实世界。从方法学的角度看,面向对象的方法是根据面向对象的世界观,按照现实世界的本来面貌理解世界和反映世界,直接围绕现实世界中的对象来构造系统。在计算机科学中,对象是系统中用来描述客观事物的一个实体,是用来构成系统的一个基本单位,而系统可以看作是由一系列相互作用的对象组成。面向对象程序设计就是运用以对象作为基本元素的方法,用计算机语言描述并处理一个问题。面向对象程序设计更符合客观世界的本来面目和人们分析问题的思维方式。为了对具有同一类属性和行为的对象进行分类描述,引入了类(class)的概念。对对象进行分类所依据的原则是所求解问题的特征。类定义了同类对象的公共属性和行为,属性用数据结构表示,行为用函数表示。可以用如下公式表示类: 类=数据结构 对数据进行操作的函数对象是类的一个实例。例如,人类是一个类,而生活在地球上的每一个人则是人类的一个对象。对象和类的关系相当于元素与集合的关系、变量与变量的“数据类型”的关系。虽然属于某个类的所有对象具有相同的属性“结构”和行为方法,但各个对象在具体的属性“值”上有所不同。对象的属性值是同类的不同对象独立存在的依据,也是这些对象的行为表现差异的基础。例如,人都有姓名、身份识别代码和性别等属性,可以将所有的人都归属于一个人类Humankind,但不同的人有不同的属性值,不同人的衣、食、住、行等行为结果也可能不同。以下给出了人类Humankind的简单描述。class Humankind {private:// 人类的属性char name[20];long ID;char sex;public:// 人类的生活行为void eat( );void wear( );void reside( );void traffic( );};结构化程序设计将数据和过程分离,而面向对象程序设计把数据和处理数据的过程当成一个整体即对象,从现实世界出发,采用对象来描述问题空间的实体,用程序代码模拟现实世界中有形或无形的对象,使程序设计过程更自然、更直观。结构化程序设计是以功能为中心来划分系统,而面向对象程序设计是以数据(表示属性)为中心来划分系统,相对于功能而言,数据具有更强的稳定性。客观世界中不同对象之间相互交流、相互作用,面向对象程序设计提供了对象之间的通信机制。程序由一些相互作用的对象(类)构成,就像人们之间互通信息一样,对象之间的交互通过发送消息来实现。程序通过执行对象的各种行为方法,来访问和改变对象的状态(属性数据),并使该对象发生某些事件。当对象发生某事件时,通常需向其他相关对象发送消息,请求它们作出一些响应。面向对象程序设计把一个复杂的系统分解成多个功能独立的对象(类),然后把这些对象组合起来,完成系统的功能。一个对象可由多个更小的对象组成,如汽车由发动机、传送系统和排气系统等组成。这些对象(类)可由不同的程序员来设计,并且设计好的对象可在不同程序中使用,这就像一个汽车制造商使用许多零部件去组装一辆汽车,而这些零部件可能不是自己生产的。采用面向对象程序设计就像流水线工作模式,最终只需将多个零部件(已设计好的对象)按照一定关系组合成一个完整的系统。面向对象的思想已经涉及软件开发的各个方面,如面向对象分析(Object Oriented Analysis,OOA)、面向对象设计(Object Oriented Design,OOD)以及面向对象的软件测试(Object Oriented Software Testing,OOST)。面向对象的应用也已经超越了程序设计的范畴,扩展到如数据库、分布式、CAD和人工智能等领域。20世纪末期由于Windows系统的广泛使用,可视化面向对象编程工具的推出,使面向对象程序设计进入了黄金时期。在硬件技术飞速发展的今天,程序设计方法也不断改进,从20世纪60年代的结构化程序设计,到80年代的面向对象程序设计,如今已开始进入基于组件的程序设计,未来或迈向面向Agent的程序设计。面向对象程序设计更适合于Windows编程。在Windows中,程序以窗口的形式出现,从面向对象的角度来看,窗口本身就是一个对象。Windows程序的执行过程就是窗口和程序其他对象的创建、处理和消亡的过程,Windows中消息的发送可以理解为一个窗口对象向别的窗口对象请求对象服务(行为)。利用面向对象的方法进行Windows应用程序的设计是极其方便和自然的。3.1.3面向对象程序设计的基本特征面向对象程序设计方法具有以下4个基本特征: 抽象、封装、继承和多态。本节从理论上对这4个基本特征进行简要介绍,在后续的内容中可以看到,C 面向对象程序设计方法都是围绕这4个基本特征展开的,是这4个基本特征的具体体现。1. 抽象把对象进行分类所依据的原则是抽象,抽象(abstract)是人类解决实际问题的常用手段。面向对象程序设计中的抽象是指对一类对象进行概括,抽出它们共同的性质并加以描述的过程。抽象的过程就是对问题进行分析和认识的过程。需要从属性和行为两个方面对对象进行描述,因此抽象分为数据抽象和行为抽象(代码抽象)。数据抽象定义了某类对象具有的共同属性或状态,行为抽象定义了某类对象具有的共同行为特征或能力。例如,对狗类Dog对象的数据抽象包括名字、品种、颜色和重量等属性,行为抽象可以包括设置狗的属性数据、输出狗的属性数据和吠声等行为方法。以下给出了Dog类的数据抽象和行为抽象的简单代码。class Dog {private:// 数据抽象char name[20]; char variety[20];char color[12];float weight;public:// 行为抽象void input();void output();void speak();};抽象并不包罗万象,即忽略对象的非本质特征,只考虑与当前目标有关的本质特征。例如,学生属于人类,可以包括很多类似于人类的属性(如姓名、性别、年龄、身高、体重)和行为。但在对学生对象进行抽象时,如果当前目标是设计学生成绩管理系统,则只关心学生对象的姓名、学号和成绩等属性,而学生的年龄、身高和体重等属性就可以忽略。但如果是设计一个户籍管理系统,则关心的属性又有所不同。良好的抽象策略可以控制问题的复杂程度,增强系统的通用性和可扩展性。2. 封装封装(encapsulation)就是将抽象得到的属性数据和行为代码有机地结合,形成一个具有类特征的整体。并且,封装决定了对象的哪些属性和行为是作为内部细节被隐藏起来,哪些属性和行为是作为对象与外部的接口。封装是实现抽象的基本手段,在C 中,利用类(class)实现对对象的抽象和封装。封装尽可能隐藏对象的内部细节,仅通过一些可控的接口与外界交互,可以防止外界随意获取或更改对象的内部数据。这样,保证通过封装得到的类具有较好的独立性。编程时一般应限制直接访问对象的属性,而应通过接口即外部方法访问,这样使程序中模块之间关系更简单、数据更安全。例如,Dog类中的name、variety、color和weight等属性属于内部数据,被定义为private私有权限;而input()、output()和speak()等行为属于外部接口,被定义为public公用权限。封装将对象的属性和行为封装成一个整体,有效地避免了外部错误对对象的影响;同时,当修改对象内部细节时,也减小了对象对外部的影响。值得说明的是,如果一味地强调封装,可能会增加编程的困难,增加程序运行开销。因此,在具体应用时应该使对象具有一定的可见性,封装好的类应该具有方便的接口,以便其他类引用。3. 继承客观事物既有共性,也有特性。如果只考虑事物的共性,而不考虑事物的特性,就不能反映出客观世界中事物之间的层次关系。抽象只考虑事物的共性,而继承是既考虑事物的共性,又考虑事物的特性,完整地描述了客观世界的层次关系。客观世界的事物之间都具有某种“继承”的层次关系,例如,人是从古猿进化而来的,人具有一些与古猿相似的共性,也具有人类自己的一些特性。面向对象程序设计的继承机制正是利用了客观世界的继承特性来构造对象。在面向对象程序设计中,继承(inheritance)是指一个新类可以从已有的类派生而来。新类继承了原有类的特性(即属性和行为)。并且,为了满足具体的需要,新类可以对原有类的行为进行修改,还可以增加新的属性和行为。例如,所有的Windows应用程序都有一个窗口,它们可以看作都是从一个窗口类派生出来的,但有的程序用于文字处理,有的程序用于绘图,这是由于根据具体需要,通过继承派生出了不同的类。继承机制很好地解决了软件的可重用性问题,并且,继承机制并不破坏对象的封装性。派生类只把从基类那里继承来的数据和操作与自己的数据和操作一并封装起来,对象依然是一个封装好的整体。在引入继承机制以后,无论对象是基类的实例还是派生的实例,都是一个被封装的实体,继承并不影响封装性。 4. 多态多态(polymorphism)是指不同对象对于同样施加于其上的作用会有不同的反应。多态是自然界常见的一种现象,体现了事物的行为的多样性。例如,太阳照射在一块冰上,其反应可能是冰块融化;而太阳照射在一块泥地上,其反应可能是泥地开裂。多态也是面向对象程序设计方法的一个基本特征,多态表现了不同对象在接收到相同的消息(命令)时会作出不同的响应。例如,对于同样的“编辑|粘贴”命令,在字处理程序和绘图程序中有不同的结果;同样的加法,把两个时间值相加和把两个整数相加的要求肯定不同。其原因是属于不同类的对象对同一消息作出的响应不同。多态使程序设计灵活、抽象,通过重载和虚函数机制很好地解决了函数同名问题。利用面向对象程序设计的抽象、封装、继承和多态等机制,程序更易于编写、维护和更新。例如,程序员可以在程序中大量使用成熟的类库(如微软基础类库MFC),从而缩短程序的开发时间,提高程序设计工作效率和程序的可靠性。3.2C 类从面向对象程序设计理论的角度来说,类是对某一类对象的抽象,而对象是类的具体实例;从程序设计语言的角度来说,类是一种复杂的自定义构造数据类型,对象是属于这种数据类型的变量。C 在C语言结构体(struct)数据类型的基础上引入了类(class)这种抽象数据类型,实现了对对象的抽象和封装。3.2.1类的定义与实现传统结构化程序设计的主要任务是编写实现不同功能的过程(子程序或函数),而面向对象程序设计的主要任务是编写包含多种属性和方法的类(class)。因此,C 面向对象程序设计实质上就是面向类的程序设计。只有在定义和实现类以后,才能声明属于这个类的对象,才能通过对象调用在类中定义的方法。C 将对象具有的属性抽象为数据成员(data member),将对象具有的行为(方法)抽象为成员函数(member function),并将它们封装在一个类中。C 类的定义在形式上类似于C语言的结构体类型,但指定了其中成员的访问权限。C 类定义的基本形式如下: class {private:;public:;protected:;};其中,class是定义类的标志关键字,是用户自定义的标识符,花括号括起来的部分称为类体,其中包括了所有数据成员和成员函数的声明。数据成员又称为成员变量(member variable),成员函数又称为方法(method)。关键字private、public和protected称为访问权限控制符,用来设置数据成员和成员函数的访问权限属性。private属性表示数据成员或成员函数是类的私有成员,这类成员只允许被本类的成员函数访问或调用;public属性表示数据成员或成员函数是公有成员,这类成员允许被本类或其他类的成员函数(通过对象)访问或调用;protected属性表示数据成员或成员函数是保护成员,这类成员允许被本类的成员函数和派生类的成员函数访问或调用。在类的外部通过对象只能访问或调用所属类的公有成员,而私有成员只能在类的成员函数中被访问或调用。一般而言,数据成员被设置为private属性,成员函数被设置为public属性,用来作为类的外部接口。注意,在声明成员时如果省略了访问权限控制符,则其属性被默认为private。例31定义表示时间的类Time。class Time {private:// 一般不要省略privateint hour;// 数据成员,表示小时int minute;// 数据成员,表示分钟int second;// 数据成员,表示秒public:void setTime(int, int, int);// 成员函数,设置时间void showTime();// 成员函数,输出时间};类Time有3个私有数据成员hour、minute和second,只能在类的成员函数中被访问或赋值;类Time有两个公有成员函数,可在类的外部被调用,被视为访问类Time的外部接口,但必须通过一个对象作为对象的成员使用(见例33)。利用C 类进行面向对象程序设计,声明类的成员只是完成了任务的第一步,最重要的任务是实现定义的类。类的实现实质上是类的成员函数的实现,即定义类的成员函数。成员函数的定义形式与一般函数基本相同,但如果在类的外部定义成员函数,必须在成员函数名前加上类名和作用域限定符(∷)。例32类Time的实现(在类的外部定义成员函数)。void Time :: setTime(int h, int m, int s)// 设置时间成员函数{hour=(h>=0 && h<24) ? h:0;minute=(m>=0 && m<60) ? m:0;second=(s>=0 && s<60) ? s:0;}void Time :: showTime()// 输出时间成员函数{cout<”引用对象的公有成员(不能引用对象的非公有成员)。例如,通过对象调用类Time的公有成员函数t1.setTime()、today.showTime()或pt1>setTime()等语句都是合法的,而任何对私有数据成员的直接访问t1.hour、today.minute或pt1>second等都是非法的。例33类Time的使用,声明对象并设置对象属性。void main(){Time EndTime;// 声明对象EndTimeEndTime.setTime(11, 45, 0);// 设置对象EndTime的时间(属性,数据成员)cout<class Time {private:int hour;int minute;int second;public:Time(int, int, int);// 构造函数~Time();// 析构函数… }; Time :: Time(int h, int m, int s){ hour=h;// 对私有数据成员初始化minute=m;second=s;cout<class Time {… Time(Time& t)// 拷贝构造函数{hour=t.hour;minute=t.minute;second=t.second;}}; int main(){Time t1(11, 45, 0);// 构造函数被调用Time t2 = t1;// 拷贝构造函数被调用}在例35中,构造函数和拷贝构造函数分别被调用一次,析构函数被调用两次。声明对象t1时系统自动调用构造函数;声明对象t2时,是利用已创建的对象t1对t2进行初始化,系统自动调用了拷贝构造函数。此外,如果将对象作为函数的参数,或将对象作为函数的返回值,调用这两类函数时也会自动调用拷贝构造函数。例36拷贝构造函数的自动调用。#include class Point {private:int x, y;public:Point(int a=0, int b=0)// 带默认参数值的构造函数{x=a;y=b;}Point(Point & p)// 拷贝构造函数{x=p.x;y=p.y;}int getX()// 成员函数,获取X坐标{return x;}int getY()// 成员函数,获取Y坐标{return y;}};void fun1(Point p)// 对象作为函数参数,调用函数时,实参对象赋值给形参对象{cout<
hour<minute<second<class A{public:int a, b;public:A(int x=0, int y=0){ a=x; b=y; }void copy(A obj)// 对象作函数参数{if (this==&obj)return;// 参数obj与当前对象是同一个对象this=obj;// 对象赋值(数据成员赋值)}void show();};void display(A pObj)// 非成员函数{cout<a<b< :: = 例如,以下语句是对类Person的静态数据成员m_nCount的初始化:int Person :: m_nCount=0;静态数据成员的访问权限属性也可以是公有、私有或保护的。对于公有静态数据成员,除了可以像一般数据成员那样,直接通过对象或在成员函数中被访问,还可以利用类名加作用域限定符(∷)来访问,这一点区别于一般的数据成员(见例38)。对于私有和保护属性的静态数据成员,只能在成员函数中被访问(初始化例外)。例38静态数据成员的使用。#include #include class Person {private:char m_strName[20];long m_ID;float m_Wage;static int m_nCount;// 私有静态数据成员,表示已创建对象的数量static float m_nTotalWage;// 私有静态数据成员,表示所有雇员的工资总额public:Person(char strName, long ID, float Wage)// 构造函数{strcpy(m_strName, strName);m_ID=ID;m_Wage=Wage;m_nCount ;// 对象数目加1m_nTotalWage=m_nTotalWage m_Wage;// 工资总额累加}void show()// 输出对象数目{cout<class Point {public:int x, y;static int m_nCount;// 公有静态数据成员,表示已创建对象的数量public:Point(int a=0, int b=0)// 带默认参数值的构造函数{x=a;y=b;m_nCount ;// 对象数目加1}static int getCount();// 静态成员函数static int getX(Point);// 对象作为静态成员函数的参数static int getY(Point);// 对象作为静态成员函数的参数};int Point::getCount(){return m_nCount;// 访问静态数据成员}int Point::getX(Point p){return p.x;// 不能直接访问非静态成员m_ID}int Point::getY(Point p){return p.y;// 不能直接访问非静态成员m_ID}int Point::m_nCount=0;// 初始化静态数据成员int main(){Point p1; cout<
评论
还没有评论。