面向对象程序设计教案_第1页
面向对象程序设计教案_第2页
面向对象程序设计教案_第3页
面向对象程序设计教案_第4页
面向对象程序设计教案_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 备 课 本(2011-2012学年第1学期) 计算机科学与技术学院信管专业2009级课程名称 面向对象程序设计 教材名称c+面向对象程序设计教程(第3版) 陈维兴 主要参考书 同类 教学大纲类型 2009院修订大纲 任课教师 岳成刚 第1章 面向对象程序设计概述【教学目的与要求】要求学生理解面向对象程序设计的基本概念;了解传统程序设计方法的局限与面向对象程序设计的优点;了解面向对象程序设计语言的发展概况。【重、难点】重点是面向对象程序设计的基本概念;难点是面向对象程序设计与传统程序设计的区别。【教学时数】2【教学方法】讲授与讨论相结合,以讲授为主。【实验项目】无【习题】教材课后习题1.1,1

2、.5 1.1 什么是面向对象程序设计简单的说,面向对象程序设计是一种程序设计方法。我们已经学习了c语言,c语言是一种结构化的程序设计语言,采用的是结构化的程序设计方法,也就是说程序是由三种基本结构组成的,在c语言中程序由函数组成,其它函数由主函数调用来完成一定的功能,而各个函数均采用这三种基本结构,即顺序结构、选择结构和循环结构。面向对象的程序设计是一种明显区别于结构化方法的程序设计方法,面向对象程序的基本元素不再是函数,而是对象;程序的组成不再是函数的集合,而是对象的集合及其交互。1.1.1 面向对象程序设计是一种新的程序设计范型正如标题所示,面向对象程序设计是一种新的程序设计方法,是一种程

3、序设计范型,所谓范型这个术语,可以理解为规范、模型或方法。面向对象程序设计范型是继面向过程程序设计范型之后非常流行的程序设计方法。该设计方法与传统过程化方法有明显的区别:面向过程程序设计范型主要特征:程序由过程定义和过程调用组成,可用公式表示成:程序过程+调用;支持面向过程程序设计范型的语言有c语言、pascal语言等。面向对象程序设计范型主要特征:程序由对象和消息组成,可用公式表示成:程序对象+消息;支持面向对象程序设计范型的语言有c+、java、c#等。其中c+不仅支持面向对象程序设计范型,同时也支持面向过程程序设计范型,是一种混合型语言。1 1.1.2 面向对象程序设计的基本概念基本概念

4、是理论基础,与具体的程序设计语言无关。j 对象对象这个词语在我们日常生活中是一个使用频率很高的词,在现实生活中对象无处不在,如我在教室里给同学们上课,这里面就有很多对象,我就是一个对象,是一名教师,同学们也是对象,课也是对象,教室同样是对象。大家有没有发现在这句话里所有的名词都是对象。抽象的东西同样也是对象,可以说任何事物都是对象,在面向对象程序设计范型中的对象是对现实生活中对象的一种模拟,在面向对象程序设计范型中,对象是描述属性的数据和对属性数据施加的一组操作的统一体。举个例子,张三是我们班的一名同学,那么对象属性有学号、姓名、成绩等,对象操作有看书、写字等。j 类在现实世界中,类是对一组具

5、有相同属性和行为的对象的抽象,如张三、李四都是人,都具有相同的生理构造和相同的行为方式。类和对象之间的关系是抽象与具体的关系,对象是类的一个实例。这种关系和c语言中的数据类型与变量的关系并没有什么两样。如int a,b;int是一种数据类型,a,b是两个不同的变量,a,b具有相同大小的存储空间及相同的加减乘除操作,都是整型变量。在面向对象程序设计范型中,类是对具有相同数据结构和相同操作的一类对象的描述。在c+语言中,数据称为数据成员,操作是用函数来完成的,称为成员函数。在用面向对象程序设计语言描述类与对象时,总是先声明类,再由类来生成该类的对象。可以说类就是生成对象的数据类型,只不过这个数据类

6、型是用户自定义的数据类型。有点类似于c语言中的结构体,只不过c语言中的结构体只有数据而没有操作。假设person是一个已经声明好的类,大家比较一下下面两条语句:person p1,p10;int i1,i10;这两条语句是不是很相似呢?j 消息与方法现实世界中各对象之间互相联系,互相作用,如我给大家讲课,同学们有在听课的行为。同样在面向对象程序设计范型中对象之间也是互相作用的称为对象的交互。对象之间的交互是通过消息传递的机制来完成的,发送消息的对象是消息的发送者,接收消息的对象是接收者。就讲课这个例子来讲,教师讲,学生听,教师是消息的发送者,学生是消息的接收者。在具体的实现面向对象程序设计范型

7、的语言中,向某个对象发送消息是通过调用该对象的成员方法(函数)来实现的。消息与方法的关系是:对象根据接收到的消息调用相应的方法,反过来,有了方法,对象才能响应相应的消息。2 1.1.3 面向对象程序设计的基本特征面向对象程序设计方法具有4个基本特征:j 抽象抽象是对具体事物的共性的一个归纳,在抽象过程中通常忽略与当前主题无关的方面,是对复杂世界的简单表示。如在学生成绩管理系统中,我们只关心学生的学号、姓名、成绩等数据而忽略其身高等数据,而在学生健康管理系统中,身高数据是必须的,相反成绩等数据就不重要了。在面向对象程序设计中的抽象包括数据的抽象和行为抽象,抽象的结果就是声明了一个类型。在c+、j

8、ava、c#等语言中,这种类型就是类(class)。类是对象的抽象,而对象是类的实例。在person p1,p10;语句中person就是一个类名,而p1是一个对象,p是一个含有10个对象的对象数组,每个对象都有person类的属性和行为。在面向对象程序设计方法中,对一个具体问题的抽象分析的结果就是通过类来描述和实现的。如在学生成绩管理系统中,对所有学生进行归纳、分析,抽象出其中的共性,可以得到:共同的属性:学号,姓名,成绩。共同的行为:录入成绩、修改成绩、输出成绩等。j 封装在现实世界中,封装就是包装,使外界不知事物的具体内容。在面向对象程序设计中,封装就是把数据和操作代码集中起来放在对象内

9、部,尽可能隐藏对象的内部细节。使用一个对象时,只要知道它向外界提供的接口而无需知道它的数据结构细节和实现操作所使用的算法。如我们看电视,只要知道开机,换频道和调声音就行了,没必要知道电视机的内部结构和工作原理。电视机上的几个按钮就是对人们提供的接口。封装的好处是将对象的使用者与设计者分开,隐藏了复杂性,提供了代码的复用性,从而大大提高了软件的开发效率。封装性是面向对象程序设计中一个重要特性,该特性有利于数据安全。如电视机和电脑的机壳保护了里面的元器件一样。j 继承继承体系了各相关类之间的“是一种”的关系,如狗是一个哺乳动物。就是说狗类继承了哺乳动物类的所有特性。继承使类之间具有层次关系。若b类

10、继承类a,则类b包含了类a的数据和操作,同时也可加入自己所特有的新的数据和操作。这时a类称为父类或基类,b类称为派生类或子类。类b是从类a派生的。面向对象程序设计提供的继承机制的作用有两个:一是避免公用代码的重复开发,二是通过增加一致性来减少模块间的接口。继承机制很好的体现了“软件重用”的思想,通过继承,派生类可以重用已有软件中的一部分甚至大部分,只需要在派生类中描述基类中没有的数据和操作,大大节省的编程的工作量,同时,派生类还可以覆盖、修改或重新定义基类中的操作。继承从基类个数的多少可以分成单继承与多继承。c+支持多继承,但java却不支持。单继承指基类只能是一个,而多继承中基类至少有两个。

11、多继承容易3 产生歧义。j 多态面向对象程序设计中的多态是对现实世界中多态的一种模拟,如学生学习这个现象,不同学生的学习方法是不一样的,如小学生的学习主要是死背,而大学生的学习主要使用的是理解记忆。面向对象程序设计中的多态性是指不同对象接收到相同的消息时执行不同的操作。如对于众多的形状类对象都有求面积的方法,但不同的形状对象求面积的公式是不一样的。c+语言支持编译时的静态多态性和运行时的动态多态性,分别是通过函数重载和虚函数来实现的。多态性增加了软件的灵活性和通用性,允许用户建立明确、易懂的通用软件。1.2 为什么要使用面向对象程序设计1.2.1 传统程序设计方法的局限性传统的程序设计是面向过

12、程的结构化程序设计,其局限性至少表现在以下几个方面:j 生产效率低下自第一台计算机问世以来,计算机硬件水平在突飞猛进的发展,而软件的生产能力还是比较低下,体现在开发周期长,效率低,费用高,曾经出现了所谓的“软件危机”。在面向对象程序设计出现之前,人们一直采用结构化的程序设计来解决问题,其主要思想是面向过程的,即功能分解并逐步求精。如pascal语言和c语言都集中体现了这种结构化的设计思想。这种采用结构化思想的软件构造方式,缺乏大粒度、可重用的构件,软件的可重用问题没有得到很好的解决。同时随着软件规模越来越大,结构化程序的数据和操作分离的特性使得软件的维护与更新变得几乎不可能,严重时软件必须重写

13、。传统的程序设计方法很难解决软件的重用性、复杂性和可维护性问题。 j 难以表示复杂的信息类型随着软件规模的增大,采用传统的程序设计方法的语言需要有更大的信息表示与处理能力,但这是面向过程的程序设计语言所不具备的。j 难以适应新环境难以适应并行处理、分布式、网络和多机系统等新的程序运行环境。总之,传统程序设计方法难以满足软件开发的需要。面向对象程序设计方法由此应运而生,很好地解决了上述面向过程的程序设计方法的局限性。满足了软件开发的需要。1.2.2 面向对象程序设计方法的优点j 提高了程序的重用性面向过程程序设计的重用性体现在标准函数库的使用上,只提供了非常基本4 的功能;而面向对象程序设计的重

14、用性体现在类库上,类库中的类不仅可以直接使用,而且可以在类库中类的基础上派生新类,对基类进行扩充和修改以满足应用需求,极大的提高了程序的重用性,因此有人将类称为“软件ic”(软件集成电路)。j 有效控制了程序的复杂性面向过程程序设计数据与操作相分离,控制程序的复杂性是程序员沉重的负担,而面向对象程序设计采用封装与信息隐藏技术,将数据与操作放在一个类中形成一个不可分割的整体,有效的控制了程序的复杂性。j 改善了程序的可维护性面向过程程序设计方法生产出来的软件很难维护,是软件危机的突出表现,而面向对象程序设计方法产生的软件则容易维护,只要类接口没有改变,类里面的数据表示和操作的实现可作随意修改。比

15、如电视从模拟电视变成了数字电视,但只要遥控器没有变,我们仍然可以很方面的看电视。同时,面向对象程序设计中的封装机制使非法操作成为不可能,大大减少了程序的出错率。j 更好的支持大型的程序设计面向对象程序设计采用类作为基本的软件模块,更好地支持大型的程序设计,可将一个任务系统进行分工,每个程序员可以独立设计,测试自己负责的模块。j 增强了计算机处理信息的范围面向对象的程序设计更接近人类的思考方式,更容易描述、抽象现实世界,实际上是大大增强了计算机处理信息的范围。j 能很好适应新的硬件环境面向对象程序设计中的对象、消息传递等思想和机制与分布式、并行处理、多机系统及网络等硬件环境正好吻合,容易在这些平

16、台上开发软件。总之,面向对象程序设计解决了面向过程的程序设计的所有局限性。是软件开发史上一个重要的里程碑,现代的程序设计语言几乎都是面向对象的程序设计语言,都是采用面向对象的程序设计范型。1.3 面向对象程序设计的语言j c+j javaj c# 5 第2章 c+概述【教学目的与要求】要求学生了解c+语言的特点,熟练掌握c+源程序的构成;牢记c+在非面向对象方面对c的扩充。【重、难点】重点是c+程序的构成;难点是c+在非面向对象方面对c的扩充。【教学时数】6【教学方法】讲授与演示相结合,以演示为主。【实验项目】c+编程入门练习【习题】教材课后习题2.2,2.4,2.18,2.19,2.20,2

17、.222.1 c+的起源和特点2.1.1 c+的起源c+是从c演变而来的,最初被称为“带类的c”,c+经过20多年的发展,至今仍是一种充满活力的程序设计语言。c+继承了c语言原有的高效性、灵活性精髓,扩充了面向对象机制,弥补了c语言不支持代码重用、不宜作大型软件的开发等不足,成为一种既支持面向过程程序设计又支持面向对象程序设计的混合型程序设计语言。2.1.2 c+的特点j c+全面兼容c,是c的超集j 全面支持面向对象机制2.2 c+源程序的构成2.2.1 一个简单的c+程序6 不过可进行行注释,采用了新的头文件形式,在输入输出上采用预定义的输入输出流对象。2.2.2 c+程序的结构特性上例只

18、是一个简单的c+程序,并没有体现面向对象程序风格,一个真正的面向对象程序由类的声明和类的使用两大部分组成。后面我们将出逐步给出能运行的c+程序,本章主要讲c+在非面向对象部分对c语言的扩充。2.2.3 c+程序的编辑、编译、连接和执行开发c+程序的过程通常包括编辑、编译、运行和调试等步骤,有很多集成开发平台可以帮助我们完成c+程序的开发,例如最常见的vc+ 6.0,本课我们就使用这个开发平台。大家在学习c语言的时候用的什么平台,我在给09网络上c课程时用的就是这个集成化的开发平台。采用的是win32 console application的工程类型,如果大家学习c时也是用vc6,对它应该不会陌

19、生。若没有使用,则应该查阅本书的上机指导书。2.3 c+在非面向对象方面对c的扩充c+是c的超集,所有c语言的语句依然可以在c+中使用,c+不仅增加了面向对象机制,而且在非面向对象方面也增加了一此新的特性。2.3.1 行注释行注释的符号是/,顾名思义,行注释用来对一行的语句进行注释。c语句的注释方法在c+中仍可使用,主要用于语句块的注释。2.3.2 c+的输入输出用cin来从键盘接收数据,用cout来向显示屏输出数据,同时c语言中的printf和scanf两个函数也是可以在c+中使用的。只不过c+的输入输出更容易使用。7 c+输出数值时采用的默认数制是十进制,如果想用八进制或十六进制输出2.3

20、.3 灵活的局部变量声明在c+中,允许变量声明与可执行语句在程序中交替出现,这在c语言中是不允许的,除非使用语句块。c+允许变量在使用前在任意位置定义,极大提高了程序的灵活性。当然也可采用c语言的定义形式,到底采用哪种形式,一个合理的建议是:在大函数中,在最靠近使用变量的位置声明,而在较短的函数中把变量集中在函数开始处说明较好。8 2.3.4 结构名、联合名与枚举名可直接作为类型名在c+中,结构名、联合名、枚举名可直接作为类型名,而在c语言中必2.3.5 constc+中,可用const关键字定义常量,完全可取代c中的#define预编译指令,它消除了#define的不安全性。但两者有本质的区

21、别,#define是完全的宏替换,在预编译阶段完成简单替换,定义的符号不占用内存空间,没有数据类型。而const定义的常量是占用内存空间而且有数据类型的。下例演示了const取代9 const也可与指针一块使用,它们组合使用情况较复杂,可归纳为三种: j 指向常量的指针变量:如const char *name=”zhang”;j 指向变量的常指针:如char * const name=”zhang”;j 指向常量的常指针:如const char * const name=”zhang”2.3.6 内联函数在函数说明前加上关键字“inline”,就表示该函数是内联函数,可使c+编译器将函数体中的

22、代码插入到调用该函数的语句处,同时用形参取代实参,而不会执行函数调用,是一种用空间换时间的措施。通常只有在规模很小而且使用频繁的函数才定义为内联函数,内联函数与带参宏定义有很大区别。内联函数的使10 2.3.7 带默认参数的函数c+允许在定义函数时,给出部分参数的默认值,具体的定义形式见如下程11 2.3.8 函数的重载所谓函数重载就是允许函数名相同而参数类型或个数不同。这在c语言中是不允许的,c+中,当两个或多个函数共用一个函数名时,称为函数的重载。函数重载的好处是极大的减少了重复代码量。参考如下两个函数重载的示例。注要定义三个版本的函数,名字且不能相同,非常繁琐。上面的例子演示的是参数12

23、 2.3.9 作用域运算符:通常如果两个变量同名,内层的同名变量为屏蔽外层的同名变量,若想在局部变量的作用域内使用同名的外层变量,则应使用作用域运算符:。如下两个示 13 2.3.10 强制类型转换c+不仅支持c语言的强制类型转换格式,而且支持一种类似函数调用形式2.3.11 new、deletec语言使用函数malloc和free动态分配内存和释放内存,c+在c的基础上可用运算符new和delete来进行内存分配。一个使用new和delete运算符的示而且最好对动态内存是否分配成功进行检查。若分配成功,返回值是非null的。若返回值为null,则表示内存分配失败。14 2.3.12 引用引用

24、的本质是为变量起一个别名,一个变量可以有多个引用,声明一个引用时必须同时进行初始化,对引用的操作实际上就是对其引用变量的操作。定义引用并不会产生新的内存需求。明的同时必须初始化,引用可以与指针起到相同的作用,但工作原理是不一样的,指针是通过地址间接访问某个变量,而引用是通过别名直接访问变量,且引用更用,也没有引用的指针。引用可以作为函数的参数和返回值,引用作为参数可以实现指针作为参数的功能,指针作为函数参数我们已经在c语言中学习了,下面给出引用作为参数15 的示例,两者可实现完全一样的功能,即交换两个数据。只不过大家要注意两者16 第3章 类和对象【教学目的与要求】要求学生熟练掌握类与对象的基

25、本概念,掌握用c+语言定义类与对象的方法,掌握对象的构造与析构,熟悉对象参数、对象数组与对象指针,对象的赋值与复制,类的静态成员与友元,类的组合应用。【重、难点】重点是类及对象的定义与使用、对象的构造与析构;难点是对象参数、对象的赋值与复制,类的静态成员与友元、类的组合应用。【教学时数】10【教学方法】讲授与演示相结合,以演示为主。【实验项目】类与对象【习题】教材课后习题3.2,3.6,3.14-3.20,3.22,3.30,3.33,3.363.1 类和对象的基本概念类是进行封装和数据隐藏的工具,对象是类的实例。类与对象是进行面向对象程序设计的关键。3.1.1 结构体与类c+中继承支持c中的

26、结构体并对其进行了扩充,使结构体不仅支持数据的定义而且还可以包括函数。下面用一个复数的绝对值示例演示了c+对c结构17 型,那就是类。类类型与结构体类型都是抽象数据类型,那么类类型与结构体类型有何区别呢?大家可将上例中的关键字struct修改成class,重新编译程序就可以看到会出现编译错误。原因是c+为了保护类中数据的安全,将数据分为两类:私有成员和公有成员。私有成员只能被类内的成员函数访问,不能被类外对象访问,公有成员既可被类内成员函数访问,也能被类外对象访问。在默认情况下,即不指定成员的访问属性的情况下,结构体中的所有成员都是公有的,而类中的成员都是私有的,除此之外,类和结构体完全相同。

27、在实际应用中,一般把需要保护的数据设置为私有的,而把成员函数设置为公有的,作为类与外界的接口。class 类名标识符private:私有数据成员和函数成员public:公有数据成员和函数成员; 18 既然c+有定义类的机制为什么还要支持结构体的定义呢,这完全是为了和c兼容。所以尽管类和结构体功能基本相同,但是建议大家尽量使用类来定义抽象数据类型,写出完全体现c+面向对象风格的程序。大家在学完后面的章节时会发现类中成员的访问属性控制符还有protected,在这里描述类定义形式中并未给出,这是为了降低问题的复杂性。后面章节将会详细介绍。3.1.2 成员函数的定义我们在写上面复数例子程序的时候,在

28、类中写了两个函数,写在类中的函数都是内联函数,尽管我们在写时并没有加上inline关键字。属于某个类的函数就是成员函数,与普通函数的定义类似。只不过成员函数的定义还有其它两种形式。下面再以三个示例来说明这三种方式。j 方式一:类内声明,类外实现(推荐)这种方式定义的成员函数是普通的成员函数,不是内联的成员函数,一般在头文件中进行类的声明,类声明中包含数据成员定义和成员函数的声明;另外还19 写c+程序推荐使用的良好风格,用vc6向导生成的代码都是采用这种风格。可以演示一下给同学们看看。最后要说明的一点就是要注意在类的实现文件中,成员函数的定义方法与以前c函数定义方法的区别,使用了作用域运算符。

29、j 方式二:类内声明并实现(隐式内联成员函数)在声明类的同时,实现了其中的成员函数,这种方法与上面写的复数例子完全一样,大家可参照上面复数的例子,对这个点运算的例子进行改写,作为课后20 这个文件写个主函数,测试了上面写好的point类。在编译时,内联函数中的代码会被展开到相应位置,而不会去调用函数,这与前面讲的普通内联函数并没有什么两样。j 方式三:显式内联成员函数所谓显式内联成员函数,就是在类内声明成员函数时加了inline关键字并不实现该函数,成员函数的实现是在类体的外面。这里要特别注意与方式一的区别,显式内联成员函数的类外实现必须与类定义在同一个文件中。用这种方式实现相程序会在链接的时

30、候发生错误,可以演示一下给同学们看看。程序可以完全相同,大家可以看出,完成同一个功能的程序可能有多种写法,类21 完全将数据和功能进行了封装,类的使用者完全不用知道类是如何实现的,只要知道该类对外提供了哪些接口就可以使用该类了,所谓类的接口就是类声明中的公有成员函数。一个人可将自己写好的类提供给他人使用,实现了源码级别的“代码重用”。事实上,著名的mfc类中有很多类,大家可以直接拿来使用,而不用自己什么程序都开始重头编写了。3.1.3 对象的定义及使用j 类与对象的关系类就是用户声明的一个数据类型,每种数据类型都是对一类数据的抽象。类与对象之间的关系大家可以看成是数据类型与变量之间的关系。c+

31、中把类的变量称为类的对象,也称为类的实例。j 对象的定义有两种方法定义对象,一是在声明类的同时,直接定义对象;二是声明类之后,在使用时再定义对象。定义对象的格式与定义基本数据类型变量的格式一样。j 对象中成员的访问只要是公有的成员,不论是数据成员还是函数成员,都可在类的外部通过类的对象进行访问。访问这些成员通常有三种方法:一是通过对象名和对象选择符访问,其一般形式是:对象名.数据成员名或对象名.成员函数名(实参表);实例分析演示;二是通过指向对象的指针访问,其一般形式是:对象指针名->成员数据或对象指针名->成员函数名(实参表);三是通过对象的引用访问。实例分析与演示。3.1.4

32、类的作用域和类成员的访问属性所谓类的作用域是指在类的声明中的一对花括号所形成的区域。在类作用域内,一个类的任何成员函数可以不受限制访问类中所有成员,而在类作用域外,对该类的成员访问是根据成员的访问属性来决定的。到目前为止,我们可以将类的成员访问属性归纳为两类:公有和私有。还有一种是保护属性,我们在下章介绍。公有成员不仅在类内可访问,而且在类外也可通过该类对象进行访问,而私有成员则只能在类内能被访问。举例验证说明。一般来说,公有成员是类的对外接口,而私有成员是类的内部数据或内部实现,不希望外部访问。将类的成员划分不同的访问级别有两个好处:一是信息隐藏;二是数据保护。3.2 构造函数与析构函数构造

33、函数与析构函数是用来完成对象的建构与销毁,它们都是属于某个类的成员函数,可由用户提供也可由系统自动生成(默认构造函数与默认析构函数)。22 3.2.1 对象的初始化和构造函数在定义对象时,对数据成员赋初始值,称为对象的初始化。在定义对象时,如果没有对数据成员赋予初始值,则它的值是不可预知的。如果一个类中所有的成员都是公有的,则可以在定义对象时对数据成员进行初始化,这种方法类似于结构体变量的初始化,但若类中有私有或保护成员时,则不能使用该方法,这时可使用公有成员函数来完成初始化,但更好的方法是使用构造函数。构造函数是一种特殊的成员函数,主要用于对象分配空间,进行初始化,构造函数的名字与类名相同,

34、可以有形式参数,但不能有返回值,构造函数可以进行重载。并且该函数是在定义对象时被自动调用的。在实际应用中,通常需要给每个类定义构造函数,如果没有给类定义构造函数,则编译系统会自动的生成一个默认的构造函数,默认的构造函数不带任何参数,函数体也是空的,它只能为数据成员开辟存储空间,而不能对对象中的数据成员赋值。教材实例分析演示。3.2.2 用成员初始化列表对数据成员初始化除了在构造函数中用赋值语句对数据成员进行初始化,还可用成员初始化列表来实现数据成员的初始化。这种方法不是在函数体中用赋值语句对数据成员初始化,而是在构造函数首部用成员初始化列表完成。其一般形式是:数据成员名(初始值),数据成员名(

35、初始值),在c+中某些类型的成员只能通过成员初始化列表来完成初始化,如const数据成员,引用类型的数据成员都只能用成员初始化列表来初始化。教材实例分析演示。数据成员是按照它们在类中的声明顺序来进行初始化的,与它们在成员初始化列表中列出的顺序无关。教材实例分析演示。说明了上面这句关键的话。3.2.3 构造函数的重载与一般成员函数或函数类似,构造函数也可以进行重载,只要参数类型或参数个数不同即可。教材实例分析演示。如果在类中用户没有定义构造函数,系统会自动提供一个函数体为空的默认构造函数,但是只要类中定义了一个构造函数,系统将不再给它提供默认构造函数。教材实例分析演示。尽管构造函数可以重载,但在

36、定义一个对象时,只执行其中一个构造函数,到底执行哪个,则视提供的实际参数而定。教材实例分析演示。23 3.2.4 带默认参数的构造函数教材实例分析演示。如果构造函数在类的声明外部定义,默认参数应该在类内声明时指定,而不能在类外定义时指定;若全部参数都是默认参数,则不应再写出默认构造函数,否则会产生歧义导致编译通不过;在一个类中定义了全部的默认参数的构造函数后,不能再定义重载构造函数,因为这样也会产生歧义。因此不能同时使用构造函数的重载和有默认参数的构造函数。3.2.5 析构函数析构函数通常用于执行一些清理任务,如释放分配给对象的内存空间等。析构函数名与类名相同,但前面必须加一个波浪号;析构函数

37、不能有返回值类型;析构函数也没有参数,不能被重载,因此析构函数只能有一个。在撤销对象时,析构函数会被自动调用。教材实例分析演示。每个类必须有一个析构函数,若没有显式的定义析构函数,则编译系统会自动的提供一个默认的析构函数,函数体为空。对于大多数类而言,默认析构函数就能满足要求,但在需要进行动态存储申请和释放时,则应该提供析构函数,教材上的示例分析与演示。析构函数在对象超出其作用域时,会被自动调用。另外,如果一个对象是用new运算符动态创建的,则在使用delete运算符释放时,delete会自动调用析构函数。24 3.3 对象数组与对象指针3.3.1 对象数组对象数组是对象的数组,每个元素都是一

38、个对象,不仅有数据成员还有函数成员。定义对象数组的一般形式是:类名 数组名下标表达式;建立对象数组时,同样要调用构造函数,有几个数组元素就要调用几次构造函数。如果构造函数只有一个参数,在定义对象数组时可以直接在等号后的花括号内提供实参。教材实例分析演示。与基本数据类型的数组一样,在使用对象数组时也只能访问单个数组元素。 教材实例分析演示。以上例子中的构造函数只有一个参数或没有参数,如果构造函数有多个参数,则在定义对象数组时只需在花括号中分别写出构造函数并指定实参即可。教材实例分析演示。在对象数组超出其作用域时,系统会自动对每个对象数组中的对象调用析构函数。3.3.2 对象指针对象指针就是存放对

39、象地址的变量。说明对象指针的语法与说明其他数据类型指针的语法完全一样。使用时,首先要把它指向一个已创建的对象,然后才能用指针进行操作。用对象指针可进行单个对象的访问,也可进行对象数组的访问。一般而言,当指向对象数组的指针加减1时,总是表示指向下一个或上一个对象。教材实例分析演示。修改成对象数组后分析演示对象数组指针的应用。3.3.3 this指针实际上,c+编译系统只用一段空间来存放类的函数成员,各个类的对象共享这些函数成员,不象数据成员,各个对象都有自己的。也就是说,成员函数的代码是存储在对象空间之外的。每个对象都有属于自己的数据成员,但是所有对象的成员函数代码却合用一份。c+为成员函数提供

40、了一个名字为this的指针,每当创建一个对象时,系统就把this指针指向该对象,即this指针的值是当前调用成员函数的对象的起始地址。在通常情况下,this指针是隐含存在的。教材实例分析演示。25 3.4 string类c+不仅支持c中的字符串,也支持字符串类string。建议大家使用string类,该类将串数据和串操作进行了很好的封装,完全是面向对象的形式。使用string类必须在程序的开头包含头文件string。3.5 向函数传递对象3.5.1 使用对象作为函数的参数对象作为函数的参数与传递基本类型的变量类似,也是按“传值调用”的方式进行。教材实例分析演示。3.5.2 使用对象指针作为函数

41、的参数对象指针作为函数参数,实现了“传地址调用”。教材实例分析演示。3.5.3 使用对象引用作为函数的参数使用引用作为函数参数也可以修改实参对象的值,但引用将更直接简单。 教材实例分析演示。3.6 对象的赋值和复制3.6.1 对象赋值同类型的对象之间可进行赋值操作。教材实例分析演示。两个对象音的赋值,仅仅使这些对象中的数据成员相同,两个对象仍是分离的,对象赋值是通过默认赋值运算符函数实现的,关于赋值运算符函数将在运算符重载的相关章节讲述。将一个对象的值赋值给另一个对象时,多数情况下是成功的,但当类中有指针成员时,可能会产生错误。这将在第5章中分析。26 3.6.2 拷贝构造函数对象的复制是通过

42、拷贝构造函数的调用来完成的。拷贝构造函数是一个特殊的构造函数,其形式参数是本类对象的引用。其作用是在创建一个新对象时,使用一个已经存在的对象进行初始化。每个类都必须有一个拷贝构造函数,如果程序中没有给出拷贝构造函数,系统会自动生成一个。系统生成的拷贝构造函数,用于复制出数据成员完全相同的新对象。程序员也可自定义拷贝构造函数。教材实例分析演示。可以看出,当用一个对象去初始化另一个对象时,可以有选择的复制。 调用拷贝构造函数有两种方式:一种形式是:类名 对象2(对象1);另一种形式是: 类名 对象2对象1;大家注意这种形式调用拷贝构造函数与对象间赋值的区别:赋值运算符用于已有值的对象上,也就是说,

43、拷贝构造函数只有在定义一个新对象并且用已有的对象进行初始化时才调用;而赋值运算符函数在已初始化(已定义)时才被调用。27 型的数据成员时,调用默认的拷贝构造函数有时会产生错误。默认拷贝构造函数的使用示例分析演示。调用拷贝构造函数的3种情况:一:当用类的一个对象去初始化另一个对象时;二:当函数的形参是类的对象时;三:当函数的返回值是类的对象时。3.7 静态成员包括静态数据成员和静态函数成员。3.7.1 静态数据成员在一个类中,若将一个数据成员说明为static,这种成员称为静态数据成员。与一般成员不同,无论建立多少个类的对象,静态数据成员只有一份,实现了同一个类中不同对象之间的数据共享。教材实例

44、分析演示。静态数据成员的定义与普通数据成员相似,但定义时前面要加上static声明。但静态数据成员的初始化与普通数据成员的初始化不同,要在类外单独进行,而且应在定义对象之前进行。初始化的一般格式如下:数据类型 类名:静态数据成员名初始值;静态数据成员属于类,而不像普通数据成员属于某个对象。静态数据成员在任何类对象创建之间就存在。静态数据成员可能过类名来访问,也可通过类的对象来访问,但建议使用类名来访问。教材实例分析演示。c+支持静态数据成员的一个重要原因是可以不必使用全局变量。3.7.2 静态函数成员静态成员函数只能访问静态数据成员,不能访问非静态成员函数或非静态数据成员,与非静态成员函数相比

45、,静态成员函数没有this指针。若想通过静态成员函数实现对非静态成员的访问,只能通过参数传递。 教材实例分析演示。28 3.8 友元c+中的友元为数据隐藏机制开了一个小孔,通过友元,可以在类外访问类的私有及保护成员,公有成员就不用说了。友元包括友元函数和友元类。3.8.1 友元函数友元函数可以是一般函数也可以是另一个类的成员函数。在类中声明友元函数时,应在函数头部加上关键字friend,声明的位置不限,友元函数不属于声明所在的类。友元函数的定义可在声明所在的类内也可在类外。将非成员函数声明为一个类的友元函数示例分析与演示。一个非成员函数同时声明为两个类的友元函数实例分析与演示。一个类的成员函数

46、作为另一个类的友元函数实例分析与演示。友元函数的使用虽然提高了程序的运行效率,但破坏了信息的封装性,因此使用友元应慎重。3.8.2 友元类当一个类被声明为另一个类的友元时,该类的所有成员函数均是另一个类的友元函数。意味着所有成员函数均可访问另一类的所有成员。教材实例分析演示。友元关系是单向的,也不具备传递性。3.9 类的组合在一个类中内嵌另一个类的对象作为数据成员,称为类的组合。当创建类的对象时,如果这个类具有内嵌的对象成员,那么内嵌的对象成员也将被自动创建。对象成员的初始化应在构造函数的初始化列表处完成,其初始化的次序是按内嵌对象成员的声明次序的。教材实例分析演示。3.10 常类型常类型的引

47、入是为了防止数据被改动。3.10.1 常引用常引用不允许对其引用的对象进行更改。在实际应用中,常引用通常用来作为函数的参数。这样可避免通过函数调用改变了实参的值。教材实例分析演示。29 3.10.2 常对象一个对象在定义是用const修饰,则被定义为常对象。常对象的数据成员在其生存期内不允许被修改。教材实例分析演示。3.10.3 常对象成员包括常数据成员和常对象成员。类中使用const声明的数据成员称为常数据成员。常数据成员只能通过成员初始化列表进行初始化。教材实例分析演示。常成员函数指成员函数首部末尾有const声明。常成员函数可以访问常数据成员和普通数据成员,常对象只能调用它的常成员函数,

48、而不能调用普通成员函数。常成员函数不能更新数据成员,也不能调用类中的普通成员函数。 30 第4章 派生类与继承【教学目的与要求】要求学生理解派生类的基本概念,掌握派生类的声明方法,理解派生类构造函数与析构函数的执行顺序;掌握基类成员在派生类中的访问属性的定义及调整方法;掌握用c+语言进行多重继承的定义与使用;掌握基类与派生类对象之间的赋值兼容关系。【重、难点】重点是用c+语言表示类之间的继承与派生关系;难点是基类成员在派生类中的访问控制,多重继承及基类与派生类之间的赋值兼容关系。【教学时数】8【教学方法】讲授与演示相结合,以演示为主。【实验项目】继承与派生【习题】教材课后习题4.1,4.4,4

49、.12,4.14,4.15,4.16,4.17,4.224.1 派生类的概念4.1.1 为什么要用继承采用继承是对现实世界一种很自然的描述方法。所谓继承就是新的类从已有类那里得到已有的特性,也就是说,从已有类产生新类的过程就是类的派生,类的继承与派生使得程序员无需修改已有的类,只要在已有类的基础上,通过增加少量代码的方法获得新的类,很好的解决了代码重用的问题。已有的类称为父类或基类,从父类新产生的类称为子类或派生类。总之,引入继承机制就是为了提高代码的可重用性。4.1.2 派生类的声明声明一个派生类的一般形式:class 派生类名:继承方式 基类名派生类新增的数据成员或函数成员;31 式的给出

50、继承方式,则是私有继承。类的继承方式指出了派生类成员及类外对象对于从基类继承来的成员的访问权限,后面章节有详细介绍。32 4.1.3 派生类的构成从上例可以看出employee类从person类继承下来所有的数据成员和函数成员,而且还增加了自己的数据成员和函数成员。构造一个派生类一般包括下面3部分工作:1). 派生类从基类接收成员在c+中,派生类把基类的全部成员(除构造函数和析构函数)接收过来。2). 调整从基类接收来的成员派生类通过使用继承方式来调整从基类接收过来成员的访问控制属性。上例中employee类使用公有继承方式,从person类中继承过来的成员在employee中的访问属性与其在

51、person类中的访问属性一样,没有发生改变。另一方面,派生类可以对基类的成员进行重新定义,如上例中,employee类中的print是在person类中print基础上再输出了两个数据。3). 在派生类中增加新的成员注意,在继承过程中,基类的构造函数和析构函数是不能被继承的,因此在声明派生类时,需要在派生类中定义新的构造函数和析构函数。4.1.4 基类成员在派生类中的访问属性类的继承方式有public(公有继承)、protected(保护继承)和private(私有继承)3种,不同的继承方式导致不同访问属性的基类成员在派生类中的访问属性也不相同。33 外的访问属性。4.1.5 派生类对基类成

52、员的访问规则通过示例演示分析,可得出如下结论:私有继承后,基类的成员无法在以后的派生类中再发挥作用,因此私有继承在实际应用中很少使用。基类中的私有成员无论在派生类中或类外都无法访问,基类中的保护成员在派生类中可访问,但在派生类外无法访问,基类中的公有成员在派生类中及类外均可访问。基类中的私有成员无论在派生类中或类外都无法访问,基类中的保护成员在派生类中可访问,但在派生类外无法访问,基类中的公有成员在派生类中可访问,但在派生类外无法访问。4.2 派生类的构造函数与析构函数派生类由于在基类的基础上增加了成员,因此一般情况下要提供自己的构造函数与析构函数。4.2.1 派生类构造函数与析构函数的执行顺

53、序当创建派生类对象时,首先执行基类的构造函数,再执行派生类的构造函数;当撤销派生类对象时,首先执行派生类的析构函数,再执行基类的析构函数。如下例所示:34 函数的执行次序正好与构造函数的执行次序相反。4.2.2 派生类构造函数与析构函数的构造规则简单派生类(不含对象成员、常量成员或引用成员等)的构造函数的一般形式如下:派生类名(参数总表):基类名(参数表)派生类新增加的数据成员的初始化语句序列派生类的构造函数也可写在类的外部,这时要用到作用域运算符:。若基类只使用默认的构造函数或不带参数的构造函数,则派生类中的构造函数可以不写,也可以不带冒号后的部分。只要基类的构造函数有参数,必须要定义派生类的构造函数。35 派生类的析构函数用于对新增加的数据成员的清理,基类的数据成员的清理由基类负责完成,在执行派生类的析构函数时,系统会自动调用基类的析构函数,完成对基类对象的清理。含有对象成员的派生类的构造函数的一般形式如下:派生类名(参数总表):基类名(参数表),对象成员名(参数表),对象成员名n(参数表n)派生类新增加成员的初始化语句序列执行次序是:先调用基类构造

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论