c++ 第三章.ppt





《c++ 第三章.ppt》由会员分享,可在线阅读,更多相关《c++ 第三章.ppt(73页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、面向对象程序设计面向对象程序设计第3章 类与对象 3.1 类类 类(Class)实际上是对某种类型的对象定义变量和方法的原型。它表示对现实生活中一类具有共同特征的事物的抽象,是面向对象编程的基础。类包含有关对象动作方式的信息,包括它的名称、方法、属性和事件。实际上它本身并不是对象,因为它不存在于内存中。当引用类的代码运行时,类的一个新的实例,即对象,就在内存中创建了。虽然只有一个类,但能从这个类在内存中创建多个相同类型的对象。可以把类看作“理论上”的对象,也就是说,它为对象提供蓝图,但在内存中并不存在。从这个蓝图可以创建任何数量的对象。类的出现解决了编程语言中数据类型的扩充问题,为实际问题的解
2、决铺平了道路。3.1 类类 3.1.1 类的定义类的定义类定义的一般形式如下:class 类名private:私有的成员函数私有的数据成员定义protected:保护的成员函数保护的数据成员定义public:类的公有接口;3.1 类类 类的定义由类头和类体两部分组成。类头由关键字class开头,然后是类名,其命名规则与一般标识符的命名规则一致,是类的标识。类体包括所有的细节,并放在一对花括号中。类的定义也是一个语句,所以要有分号结尾,否则会产生编译错误。数据成员是描述类状态特征的变量也称为成员变量,成员函数用来描述类的自身功能。按照面向对象分析和设计得出的结论,类中不同的成员变量和成员函数应该
3、有不同的信息隐藏程度。为叙述简洁起见,经常把类的成员变量和成员函数简称为类的成员。C+语言提供了三种不同的信息隐藏程度,分别用三种不同的关键字private、protected和public表示外界对它们的访问程度。在设计类时,一般情况下,应该将所有成员变量设计成私有的,将所有外部程序需要的成员函数(即向外部程序提供的接口)设计成公有的。3.1 类类【例3.1】设计具有加、减、乘、除运算功能的分数类。分析:如果有分数和,那么二者的相关运算规则可表示为下列形式。加运算:减运算:乘运算:除运算:3.1 类类 根据封装的特性,类的内部要封装数据及数据的操作,为保证外界不能够直接操作类内部的数据,必须
4、将成员变量的访问权限设置为私有的或保护类型的,而外界只能通过类提供的公有访问权限的成员函数来操作。对于分数类来说,成员变量包括分数的分子和分母,成员函数包括分数的加、减、乘、除运算。外部程序只需要通过类的公共接口(即公有的成员函数)来使用复数,并不需要直接操作分数的分子和分母。因此,分数的成员变量应该定义成私有的,复数的成员函数(包括复数的加、减、乘、除运算)应该定义成公有的。通常情况下,按照算法的技术要求,经计算机处理的数据必须有一个或多个输出结果供用户查阅,因此分数类的对象计算完毕后会要求进行输出显示,因此,再增加一个公有的输出成员函数,用来输出一个完整的分数对象。为了后边使用方便,把复数
5、类放在头文件中。3.1 类类 完成fraction类的设计后,就可以在应用程序中使用。使用时只需将保存有fraction类的库文件包含进可执行文件中,即可使用fraction类的功能。【例3.2】类的引入和使用程序运行的结果为:分数为:93/35分数为:33/-35分数为:54/35分数为:10/21本例中通过“fraction w(6,7),t(9,5),d;”完成了fraction类具体对象的定义,即实现了类的实例化,并对fraction类的功能进行了测试。3.1 类类 3.1.2 访问控制访问控制类成员有3种不同的访问权限:(1)私有(private)成员只能被该类的成员函数访问。在pr
6、ivate后声明的成员变量和成员函数都是外部程序不可见的,称为私有成员变量和成员函数;(2)保护(protected)成员只能被该类的成员函数或派生类的成员函数访问。在protected后声明的成员变量和成员函数在类外部中是不可见的,称为保护成员变量和成员函数。(3)公有(public)成员可以在类外访问。在public后声明的成员变量和成员函数不仅内部成员可以调用,而且对外部程序也是可见的,称为公有成员变量和成员函数。数据成员通常是私有的,成员函数通常有一部分是公有的,一部分是私有的。公有的函数可以在类外被访问,也称之为类的接口。可以根据解决的问题,灵活地为各个数据成员和成员函数指定合适的访
7、问权限。3.1 类类 3.1.3 成员变量成员变量成员变量又称为成员属性,它是描述对象状态的数据,是类中很重要的组成成分。成员变量用以维护对象的状态。不同的类对应的成员变量是不同的,同一个类的不同实例具有相同的成员变量,但它们具有不同的表示值。1.声明成员变量声明成员变量在面向对象程序设计中,类的成员变量抽象了现实世界中一类对象的属性(或状态)。因此成语变量的数据类型是丰富的,它们可以用任何基本数据类型、用户自定义的数据类型和任何类类型来定义。根据类的封装性,成员变量所表示的对象的属性值是不应允许外部程序擅自改变的,一般情况下,成员变量的访问权限应定义为私有的(private)或是保护的(pr
8、otected)。基本的定义格式为:3.1 类类 private|protected|public:数据类型 成员变量名;在例3.1中,成员变量的定义如下:private:int numerator;int denominator;分数类中的分子和分母的访问权限被设置为私有的,这意味着numerator 和denominator只能被分数类内部的成员函数所操作,类外部的功能单元只能通过分数类提供的公共接口来完成对就numerator 和denominator的操作。根据问题要求的不同,可以将成员变量的数据类型定义为基本数据类型、用户自定义的数据类型或已经定义过的类的类型;也可以将访问权限定义为
9、私有的(private)或是保护的(protected)。3.1 类类 例如,如下成员变量定义就是允许的:class A/类A;class B/类Bprotected:A x;/成员变量x的数据类型为类A类型;3.1 类类 2.成员变量的设计成员变量的设计在面向对象分析阶段确定下来的成员变量展现了类的特征,根据问题的需要可将它的数据类型和访问权限进行定义,但是在定义时还是有一定限制的。(1)成员变量不能在定义时初始化。类的对象的模板,成员变量是类的描述信息,程序编译的时候只是理解其语意,用来控制对象的内存布局和访问,并不占用内存空间,所以类的定义时不能够将成员变量初始化。例如,不能把例3.1的
10、成员变量定义成如下形式:3.1 类类 private:int numerator=0;int denominator=1;(2)成员变量不能递归定义。成员变量不能用自己所属的类型来定义自身的成员变量。例如,下述结构的类定义是错误的:class AA x;编译器在编译时会提示“error C2460:w:uses A,which is being defined”来告知用户类A正在定义中。3.1 类类 3.1.4 成员函数成员函数成员函数也称类的方法,是实现类功能的手段,类对象通过成员函数访问类中的私有成员,同时外部功能单元通过公有权限的成员函数完成对类的操作。成员函数定义成员函数定义成员函数的
11、定义体可以定义在类定义体内部,也可定义在类定义体的外部。定义在类定义体内部的成员函数的定义格式为:private|protected|public:函数返回值 函数名称(参数列表)函数体 3.1 类类 在例3.1中fraction类的所有成员函数都定义在了内定义体的内部。因此fraction类的成员函数都被编译器解释为内联成员函数。成员函数定义在定义体外部对类的功能没有影响,相对于内联函数,这种定义在类的外部的成员函数称之为外联成员函数。【例3.3】成员函数定义在类定义体外部。例3.3类定义体中,只是说明了成员函数的原型,而成员函数的定义体都放到了类定义体的外部。因为这些是类的成员函数定义而不
12、是一般的C+函数定义,所以需要在这些成员函数的名字前面加上“fraction:”,告知编译器这些函数是fraction类的成员函数。对于采用外联成员函数形式定义的类,在使用时和采用内联成员函数实现的类并没有本质的区别。例3.1和例3.3中的类定义对例3.2的功能实现都能起到相同作用。3.1 类类 2.成员函数重载成员函数重载函数重载是指同在同一个命名空间内一个函数名可以对应着多个函数的实现。类是数据和对数据操作的封装体,成员函数在类的内部可以进行重载,来完成同一调用形式的不同功能实现,成员函数重载使得对象的使用得到了简化,为外部程序用各种参数形式调用成员函数提供了灵活性。【例3.4】设计加运算
13、重载的分数类本例实现了分数加运算的重载,使分数类的计算更加灵活,更好地适应了复杂的应用环境。3.1 类类【例3.5】成员函数重载测试程序运行的结果为:分数为:62/7分数为:93/35通过对成员函数重载的测试,可以发现,如果不定义重载,就需要2个不同的函数来实现对分数加分数和分数加整数的操作。定义重载之后,只需一种形式就完成了,使得对象的使用得到了简化。3.1 类类 3.成员函数的行为限制成员函数的行为限制成员函数是类功能的具体体现,公有权限的成员函数对外提供公共接口,外部功能单元通过这些接口来操作成员变量,为了避免对类的数据成员产生误操作,可通过const关键字对成员函数进行行为限制。设计成
14、员函数时,可以用const关键字修饰参数和成员函数。const关键字修饰参数和成员函数的作用与语法含义是:(1)当成员函数的某个参数修饰为const时,表示该参数在成员函数内不会也不能被修改。(2)当成员函数修饰为const时,表示限制该成员函数只能读取当前对象的成员变量,但不能修改当前对象的成员变量。用const修饰成员函数时,关键字const既可以放在成员函数定义的最前面,也可以放在成员函数定义的最后面,但通常把关键字const放在成员函数定义的最后面。3.1 类类【例3.6】重新设计例3.1的分数类。分析:根据例3.1的分析可以知道,分数类的加、减、乘、除运算等都只需要读取分子和分母的值
15、,不需要也不应该修改它们值。因此,应该使用关键字const限定这些成员函数使其不能够修改成员变量值。本例中,分数类fraction的加、减、乘、除运算由于没有进行自身成员变量值的改变,故用const来限制它们。对于成员函数show和成员函数commonden是不能够用const修饰的,因为这两个成员函数是要对自身所在对象的成员变量进行修改的。3.2 构造函数与析构函数构造函数与析构函数数据类型包含了空间的分配和对该类数据的操作。“int a=5;”表示的意义在于:n定义了一个变量a;n内存分配4个字节的连续空间;n对a可进行数学运算操作。类为解决基本数据类型的不足提供了有效途径,自定义的类是一
16、种数据类型,它包含了数据和对数据的操作,也涉及到内存空间的分配。类和对象的关系就相当于基本数据类型与该类型变量之间的关系。对象可以看作是一个复合的数据单元,其外在的区别在于对象的名称,内在区别就是对象的属性和属性值。构造函数和析构函数是在类体中说明的两种特殊的成员函数。构造函数的功能是在创建对象时,使用给定的值来将对象初始化。析构函数的功能是用来释放一个对象的。在对象删除时,用它来做一些清理工作,它与构造函数的功能正好相反。3.2 构造函数与析构函数构造函数与析构函数3.2.1 构造函数构造函数构造函数是在对象被创建时由系统自动调用的成员函数。当定义对象时,需要在内存为对象开辟空间,并对对象内
17、部的成员变量赋初值。构造函数充当了这一角色。1.构造函数的特点构造函数的特点构造函数是一种完成对象初始化的特殊成员函数,它的定义格式和使用方法都有很强的特点。构造函数的格式为::()函数体3.2 构造函数与析构函数构造函数与析构函数构造函数的设计应注意以下几点:(1)构造函数的命名必须和类名完全相同;而一般方法则不能和类名相同。(2)构造函数不能有返回类型,即使是void也不行。这是由于构造函数返回类本身的对象,因此不需要给出构造函数返回值类型。(3)构造函数的参数用来传递定义对象时的初始值,通常情况下要注意参数的类型与成员变量的类型相匹配。(4)构造函数的参数允许使用默认值。当构造函数的参数
18、有默认值时,表示如果定义对象时给出了初始值,则使用这样的初始值;如果定义对象时没有给出初始值,则使用默认值。如果可能,最好给出构造函数所有参数的默认值,这可以方便定义对象,特别是,这样可以定义数组对象。构造函数没有默认值时,不能定义数组对象。3.2 构造函数与析构函数构造函数与析构函数(5)构造函数的访问权限一定是公有的(public),这是因为构造函数是定义对象时由系统自动调用的,对象都是在类的外部定义的,所以只有公有的访问权限才能让外部的对象看到这个类的接口。(6)构造函数可以重载,即允许一个类中有多个参数个数或参数类型不同的构造函数。2.默认的构造函数默认的构造函数每个类必须有一个构造函
19、数,否则没法创建对象。若程序没有提供任何构造函数,则C+提供一个默认的构造函数,该默认构造函数是无参构造函数,它仅负责创建对象,不做任何初始化的工作。只要程序定义了一个构造函数(不管是无参还是有参构造),C+就不再提供默认的默认构造函数。即如果为类定义了一个带参的构造函数,还想要无参构造函数,就必须自己定义。3.2 构造函数与析构函数构造函数与析构函数【例3.7】定义一个点类,示例构造函数的用法本例中定义了3个构造函数,实现了构造函数的重载,其中point()是默认的构造函数,由于定义了其它两个构造函数,point()就必须由用户自己定义出来。【例3.8】测试point类的构造函数重载程序运行
20、的结果为:点的坐标是:(4,5)点的坐标是:(3,5)点的坐标是:(5,6)3.2 构造函数与析构函数构造函数与析构函数3.2.2 析构函数析构函数析构函数(destructor)与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后”的工作。以C+语言为例,析构函数名也应与类名相同,只是在函数名前面加一个波浪符,例如stud(),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数,它也不进行任何操作,所以许多简单的类
21、中没有用显式的析构函数。3.2 构造函数与析构函数构造函数与析构函数1.析构函数的特点析构函数的特点析构函数也是一种特殊的成员函数,它的功能和构造函数互逆。它的格式为::()函数体构造函数的设计应注意以下几点:(1)析构函数名是在类名前再加上字符“”。(2)析构函数不能带任何参数,不能有返回类型(即使是void类型也不行)。(3)一个类中只能有一个析构函数。3.2 构造函数与析构函数构造函数与析构函数(4)析构函数的访问权限一定是公有的(即public)。这和构造函数的访问权限一定是公有的原因相同。(5)函数体为空的析构函数可以省略不设计。此时,系统将自动为其定义一个缺省的、函数体为空的析构函
22、数。2.默认的析构函数默认的析构函数类必须有析构函数,如果一个类没有定义析构函数,则系统会自动生成一个默认的构造函数,其格式为::()3.2 构造函数与析构函数构造函数与析构函数一般情况下,如果类中没有用new运算符动态申请内存空间,则该类的析构函数为空。并可以不设计。例如,例3.1的分数类中没有使用过new运算符,因此该类的析构函数的函数体为空。但是,如果类中用new运算符动态申请了内存空间,则该类的析构函数一定不能为空。此时,析构函数应该设计用delete运算符动态释放内存空间。如果构造函数中使用了new申请了空间,而析构函数没有使用delete运算符,会造成不再被程序使用的内存空间没有被
23、系统回收,造成内存泄漏。3.2 构造函数与析构函数构造函数与析构函数【例3.9】设计一个一维动态数组,要求析构函数不为空。本例中,构造函数在判断数组长度后进行了动态内存申请,在析构函数中对动态申请的内存用delete进行了释放,防止产生内存泄漏,并且在析构函数的最后输出提示语句。【例3.10】测试一维动态数组程序运行的结果为:0 1 2 3 4已经释放内存空间!3.2 构造函数与析构函数构造函数与析构函数如果一维动态数类的析构函数中没有进行delete操作,在for循环结束后,构造函数中用new动态申请的由指针p所指向的空间就不会释放,必将会产生内存泄露。例3.9中一维动态数组对象a在内存中的
24、空间结构如图3-1所示。图3-1 一维动态数组3.2 构造函数与析构函数构造函数与析构函数3.2.3 拷贝构造函数拷贝构造函数在某些情况下,需要用已存在的对象初始化同类的另一个对象,这时需要一种特殊的构造函数拷贝构造函数。拷贝构造函数也称复制构造函数,它的参数是本类对象的引用。拷贝构造函数的定义格式为:class 类名public:类名(参数表);类名(const 类名&对象名);3.2 构造函数与析构函数构造函数与析构函数类名:类名(const 类名&对象名)函数体;拷贝构造函数是一种特殊的构造函数,因此它具有构造函数的性质,在三种情况下拷贝构造函数会被系统自动地调用。(1)用类的一个对象初
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- c+ 第三章 第三

限制150内