C程序设计第8章类与对象.ppt

上传人:牧羊曲112 文档编号:6503644 上传时间:2023-11-07 格式:PPT 页数:37 大小:326.49KB
返回 下载 相关 举报
C程序设计第8章类与对象.ppt_第1页
第1页 / 共37页
C程序设计第8章类与对象.ppt_第2页
第2页 / 共37页
C程序设计第8章类与对象.ppt_第3页
第3页 / 共37页
C程序设计第8章类与对象.ppt_第4页
第4页 / 共37页
C程序设计第8章类与对象.ppt_第5页
第5页 / 共37页
点击查看更多>>
资源描述

《C程序设计第8章类与对象.ppt》由会员分享,可在线阅读,更多相关《C程序设计第8章类与对象.ppt(37页珍藏版)》请在三一办公上搜索。

1、1,第8章 类与对象,教学内容 8.1 类和对象 8.2 构造函数和析构函数 8.3 对象数组和对象指针 8.4对象的动态建立和释放,2,8.1 类和对象,类是C+中十分重要的概念,它是实现面向对象程序设计的基础。类是所有面向对象语言的共同特征,所有面向对象的语言都提供了这种类型。一个有一定规模的C+程序是由许多类所构成的。对象=算法+数据结构 程序=(对象+对象+对象+)+消息 或:程序=对象s+消息“对象s”表示多个对象。消息的作用就是对对象的控制。程序设计的关键是设计好每一个对象,以及确定向这些对象发出的命令,使各对象完成相应操作。,3,8.1类和对象类的声明和对象的定义,1类和对象的关

2、系 每一个实体都是对象,有一些对象具有相同的结构和特性,每个对象都属于一个特定的类型。在C+中,对象的类型称为类,类代表了某一批对象的共性和特征。前面已说明,类是对象的抽象,而对象是类的具体实例。如同结构体类型和结构体变量的关系一样,人们先声明一个结构体类型,然后用它去定义结构体变量,同一个结构体类型可以定义出多个不同的结构体变量。在C+中也是先声明一个类类型,然后用它去定义若干个同类型的对象,对象就是类类型的一个变量。可以说类是对象的模板,是用来定义对象的一种抽象类型。类是抽象的,不占用内存,而对象是具体的,占用存储空间。在一开始时就弄清对象和类的关系是十分重要的。,4,8.1类和对象类的声

3、明和对象的定义,2声明类类型 类是用户自己指定的类型。如果程序中要用到类类型,必须自己根据需要进行声明,或者使用别人已设计好的类。C+标准本身并不提供现成的类的名称、结构和内容。在C+中声明一个类类型和声明一个结构体类型是相似的。,class 类名public:/成员访问限定符 公有的数据成员和成员函数;private:私有的数据成员和成员函数;protected:受保护的数据成员和成员函数;,(1)用public声明的成员在类的内、外都可以使用。(2)用private声明的成员只能在类的内部使用。(3)用protected声明的成员可以在类的内部使用,也可以被派生类的成员函数(后代)使用。,

4、5,struct Student/声明了一个名为Student的结构体类型int num;char name20;char sex;Student stud1,stud2;/定义了两个结构体变量stud1和stud2,class Student/以class开头int num;char name20;char sex;/以上3行是数据成员void display()/这是成员函数 cout num:num endl;cout name:name endl;cout sex:sex endl;/以上4行是函数中的操作语句;Student stud1,stud2;/定义了两个类对象stud1和st

5、ud2,可以将上面类的声明改为:class Student/声明类类型private:/声明以下部分为私有的int num;char name20;char sex;public:/声明以下部分为公有的void display()cout num:num endl;cout name:name endl;cout sex:sex endl;Student stud1,stud2;/定义了两个类对象stud1和stud2,6,8.1类和对象类的声明和对象的定义,3类和结构体的异同 C+增加了类类型后,仍保留了结构体类型(struct),而且把它的功能也扩展了。C+允许用struct来定义一个类类

6、型。,(1)如果用class定义类,若既不指定public也不指定private,则系统默认为private。(2)如果用struct定义类,若既不指定public也不指定private,则系统默认为public。,7,#include class Complexprivate:double r;double i;public:void init(double rr,double ii)r=rr;i=ii;double real()return r;double image()return i;,void main()Complex a;a.init(2,3);couta.real()+“a.

7、image()iendl;a.r=6;/错误,a.i=3.2;/错误,8,数据成员可以是任何数据类型,如整型、浮点型、字符型、数组、指针、引用等,也可以是另外一个类的对象或指向对象的指针,还可以是指向自身类的指针或引用,但不能是自身类的对象。此外,数据成员不能指定为自动(auto)、寄存器(register)和外部(extern)存储类型。例如:class A;class B private:int a;A obja1;/正确A*obja2;/正确B*objb,9,在声明(或定义)类时,不能为数据成员赋初值。例如:class Aprivate:int a=0;/错误int b3=1,2,3;/

8、错误public:;,10,8.1类和对象类的成员函数,1成员函数的定义在类定义体中给出函数的声明,说明函数的参数表和返回值类型,在类定义之外给出函数的具体实现,这是一般成员函数的定义方法。与普通函数不同的是,类外定义成员函数时要指明类的名称,具体形式为:返回值类型 类名函数成员名(参数表)函数体,可以将上面类的声明改为:class Student/声明类类型private:/声明以下部分为私有的int num;char name20;char sex;public:/声明以下部分为公有的void display();void Student:display()cout num:num end

9、l;cout name:name endl;cout sex:sex endl;,再如:下面的时钟类定义class Clockpublic:void SetTime(int NewH,int NewM,int NewS);private:int Hour,Minute,Second;public:void ShowTime();,11,8.1类和对象类的成员函数,2带缺省值的成员函数 前面讲过带缺省形参值的函数,同样,类的成员函数也可以有缺省形参值,其调用规则与普通函数相同。在实际问题中,有时候这个缺省值可以带来很大的方便。例如,时钟类的函数SetTime()就可以使用缺省值。,void Se

10、tTime(int NewH=10,int NewM=1,int NewS=10);/在定义函数时,如果不指定类名,又不放在类中,就是普通函数,此处的函数是放在类中的成员函数 Hour=NewH;Minute=NewM;Second=NewS;/函数调用时,如果不给出实参,就把时间设置为10:1:10,12,8.1类和对象类的成员函数,3内联成员函数内联成员函数的声明有两种方式隐式声明和显式声明。将函数体直接放在类定义体内,这种方法称之为隐式声明。例如,将时钟类的函数ShowTime声明为内联成员函数,可以显式声明写作:inline void ClockShowTime()cout Hour:

11、Minute:Second endl;,还可以隐式声明为:class Clockpublic:void SetTime(int NewH,int NewM,int NewS);void ShowTime()cout Hour:Minute:Second endl;private:int Hour,Minute,Second;,13,内联成员函数,#includeclass pointprivate:int x,y;public:void setpoint(int,int);int getx();int gety();inline void point:setpoint(int a,int b)

12、x=a;y=b;inline int point:getx()return x;inline int point:gety()return y;main()int x=9,y=20;point p1;p1.setpoint(x,y);coutpoint.x=p1.getx()endl;coutpoint.y=p1.gety()endl;,#includeclass pointprivate:int x,y;public:void setpoint(int a,int b)x=a;y=b;int getx()return x;int gety()return y;main()int x=9,y=

13、20;point p1;p1.setpoint(x,y);coutpoint.x=p1.getx()endl;coutpoint.y=p1.gety()endl;,14,8.1类和对象类的成员访问控制,类的成员包括数据成员和成员函数,分别描述类所表达问题的属性和行为,是问题特性的不可分割的两个方面。成员数据的定义方式与一般的变量相同,只要将这个定义放在类的定义体中即可,它与一般变量的区别就在于其访问的权限可以由类来方便地控制。类成员访问权限的控制,就是类的隐藏和封装,这种控制是通过设置成员的访问控制属性来实现的。访问控制属性可以有以下三种:公有类型(public)、私有类型(private)和

14、保护类型(protected)。,15,8.1类和对象对象成员的引用,在程序中经常需要访问对象中的成员。访问对象中的成员可以有三种方法:通过对象名和成员运算符访问对象中的成员。通过指向对象的指针访问对象中的成员。通过对象的引用变量访问对象中的成员。,1、通过对象名和成员运算符访问对象中的成员class Time public:/数据成员和函数成员是公有的int hour;void display()cout hour:hour endl;void main()Time p;/定义对象p p.hour=8;/使p对象的成员值为8 p.display();,16,2通过指向对象的指针访问对象中的成

15、员class Time public:/数据成员和函数成员是公有的int hour;void display()cout hour;/输出p指向的对象中的成员t.display()、(*p).display()、p-display()三者等价,17,3、通过对象的引用变量访问对象中的成员 class Time public:/数据成员和函数成员是公有的int hour;void display()cout hour:hour endl;Time t;/定义对象tTime/输出对象t的成员hour,18,4、对象赋值对象名1对象名2;Clock*pa,*pb,aClock,bClock;bClo

16、ck=aClock;pa=new Clock;pb=pa;,1、两个对象必须类型相同2、进行数据成员的值拷贝,赋值之后,两不相干3、若对象有指针数据成员,赋值可能产生问题,19,8.1类和对象应用举例,【例8-1】一个简单的例子#include using namespace std;class Time/定义Time类public:/数据成员为公有的int hour;int minute;int sec;,int main()Time t1;/定义t1为Time类对象cin t1.hour;/输入设定的时间cin t1.minute;cin t1.sec;cout t1.hour“:”t1.

17、minute;cout:t1.sec endl;return 0;,20,例8-2:利用函数实现相同功能#include using namespace std;class Timepublic:int hour;int minute;int sec;,int main()void settime(Time,void settime(Time/输出对象中的数据,/将主函数以后改为以下内容int main()/函数声明void settime(Time,void settime(Time,21,例8-3:将上述程序改用含成员函数的类来处理。#include using namespace std

18、;class Timepublic:void settime();/公有成员函数void showtime();/公有成员函数private:/数据成员为私有int hour;int minute;int sec;,int main()Time t1;/定义对象t1t1.settime();/调用对象t1的成员函数settime,向t1的数据成员输入数据t1.showtime();/调用对象t1的成员函数showtime,输出t1的数据成员的值Time t2;/定义对象t2t2.settime();/调用对象t2的成员函数settime,向t2的数据成员输入数据t2.showtime();/调

19、用对象t2的成员函数showtime,输出t2的数据成员的值return 0;,void Timesettime()/在类外定义函数settimecinhour;cinminute;cinsec;void Timeshowtime()/在类外定义函数showtimecouthour:minute:secendl;,22,【例8-4】找出一个整型数组中元素的最大值。#include using namespace std;class Array_max/声明类public:/以下3行为成员函数原型声明void set_value();/对数组元素设置值void max_value();/找出数组

20、中的最大元素void show_value();/输出最大值private:int array10;/整型数组int max;/max用来存放最大值;,void Array_maxset_value()/成员函数定义,向数组元素输入数值int i;for(i=0;iarrayi;void Array_maxmax_value()/成员函数定义,找数组元素中的最大值int i;max=array0;for(i=1;imax)max=arrayi;void Array_maxshow_value()/成员函数定义,输出最大值cout max=max;,int main()Array_max arr

21、max;/定义对象arrmaxarrmax.set_value();/调用arrmax的函数set_value,向数组元素输入数值arrmax.max_value();/调用arrmax的函数max_value,找出数组元素中的最大值arrmax.show_value();/调用arrmax的函数show_value,输出数组元素中的最大值return 0;,23,【例】Clock类及其对象的完整例程。#include#includeusing namespace std;class Clock public:void setHour(int h)hour=h;void setMinute(i

22、nt m)minute=m;void setSecond(int s)second=s;void dispTime()coutNow is:”hour:minute:secondendl;private:int hour,minute,second;,void main()Clock*pa,*pb,aClock,bClock;aClock.setMinute(12);aClock.setHour(16);aClock.setSecond(27);bClock=aClock;pa=new Clock;pa-setHour(10);pa-setMinute(23);pa-setSecond(34)

23、;pb=pa;pa-dispTime();pb-dispTime();aClock.dispTime();bClock.dispTime();,24,8.2构造函数和析构函数构造函数,1对象的初始化 在建立一个对象时,常常需要做某些初始化的工作,例如对数据成员赋初值。如果一个数据成员未被赋值,则它的值是不可预知的,因为在系统为它分配内存时,保留了这些存储单元的原状,这就成为了这些数据成员的初始值。这种状况显然是与人们的要求不相符的,对象是一个实体,它反映了客观事物的属性(例如时钟的时、分、秒的值),是应该有确定值的。,25,8.2构造函数和析构函数构造函数,2构造函数的作用 为了解决上述问题,

24、C+提供了构造函数(constructor)来处理对象的初始化。构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对象时自动执行。构造函数的名字必须与类名同名,而不能由用户任意命名,以便编译系统能识别它并把它作为构造函数处理。它不具有任何类型,不返回任何值。构造函数的功能是由用户定义的,用户根据初始化的要求设计函数体和函数参数。,26,8.2构造函数和析构函数拷贝构造函数,可用一个对象去构造另一个对象,或者说,用另一个对象值初始化一个新构造的对象。例如:对象作为函数参数传递时,也要涉及对象的拷贝。例如:,27,8.2构造函数和析构函数默认拷贝构造函数,在类定义中,

25、如果未提供自己的拷贝构造函数,则C+提供了一个默认拷贝构造函数,就像没有提供构造函数时,C+提供默认构造函数一样。C+提供的默认拷贝构造函数工作的方法是完成一个成员一个成员的拷贝。如果成员是类对象,则调用其拷贝构造函数或者默认拷贝构造函数。,28,8.2构造函数和析构函数浅拷贝和深拷贝,在默认拷贝构造函数中,拷贝的策略是逐个成员依次拷贝。但是,一个类可能会拥有资源,当其构造函数分配了一个资源的时候(例如堆内存),会发生什么呢?如果拷贝构造函数简单地制作了一个该资源的拷贝,而不能对本身分配,就面临一个麻烦的局面两个对象拥有同一个资源。当对象析构时,该资源将经历两次资源返还。,29,8.2构造函数

26、和析构函数析构函数,析构函数与构造函数的作用正好相反,它用来完成对象被删除前的一些清理工作,也就是专门作扫尾工作。一般情况下,析构函数是在对象的生存期即将结束时由系统自动调用的。它的调用完成之后,对象也就消失了,相应的内存空间也被释放。当然,一个对象完成了它的任务后,我们可以通过使用完全的限定名(带对象名、类名和函数名)调用析构函数,将其人为地清除。析构函数也是类的一个公有成员函数,它的名称是在类名前面加“”构成的,也没有返回值说明。和构造函数不同,析构函数不接受任何参数,但可以是虚函数。如果不进行显式说明,系统也会生成一个不做任何事的缺省析构函数。,30,8.2构造函数和析构函数析构函数,例

27、如,给时钟类加入一个空的内联析构函数,其功能和系统自动生成的缺省析构函数相同:,31,8.2构造函数和析构函数调用构造函数和析构函数的顺序,在使用构造函数和析构函数时,需要特别注意对它们的调用时间和调用顺序。在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用,如图所示。,32,8.3对象数组和对象指针对象数组,数组不仅可以由简单变量组成(例如整型数组的每一个元素都是整型变量),也可以由对象组成(对象数组的每一个元素都是同类的对象)。在日常生活中,有许多实体的属性是相同的

28、,只是属性的具体内容不同。例如,一个班有50个学生,每个学生的属性包括姓名、性别、年龄、成绩等,如果为每一个学生建立一个对象,需要分别取50个对象名,用程序处理很不方便。这时可以定义一个“学生类”对象数组,每一个数组元素是一个“学生类”对象:Student stud50;/假设已声明了Student类,定义stud数组,有50个元素,33,8.3对象数组和对象指针对象指针,1指向对象的指针 在建立对象时,编译系统会为每一个对象分配一定的存储空间,以存放其成员。对象空间的起始地址就是对象的指针。可以定义一个指针变量,用来存放对象的指针。如果有一个类:,34,8.3对象数组和对象指针对象指针,在此

29、基础上有以下语句:这样,pt就是指向Time类对象的指针变量,它指向对象t1。定义指向类对象的指针变量的一般形式为:类名*对象指针名;,35,8.3对象数组和对象指针对象指针,2指向对象成员的指针 对象有地址,存放对象初始地址的指针变量就是指向对象的指针变量。对象中的成员也有地址,存放对象成员地址的指针变量就是指向对象成员的指针变量。(1)指向对象数据成员的指针。(2)指向对象成员函数的指针。,36,8.4对象的动态建立和释放,用new运算符动态地分配内存后,将返回一个指向新对象的指针的值,即所分配的内存空间的起始地址。用户可以获得这个地址,并通过这个地址来访问这个对象。需要定义一个指向本类的

30、对象的指针变量来存放该地址。例如:Box*pt;/定义一个指向Box类对象的指针变量pt pt=new Box;/在pt中存放了新建对象的起始地址 在程序中就可以通过pt访问这个新建的对象。例如:coutheight;/输出该对象的height成员 coutvolume();/调用该对象的函数volume,计算并输出体积 C+还允许在执行new时,对新建立的对象进行初始化。例如:Box*pt=new Box(12,15,18);这种写法是把上面两个语句(定义指针变量和用new建立新对象)合并为一个语句,并指定初值,这样更精炼。新对象中的height、width和length分别获得初值12、15和18。,37,8.4对象的动态建立和释放,在不再需要使用由new建立的对象时,可以用delete运算符予以释放。例如:delete pt;/释放pt指向的内存空间 这就撤销了pt指向的对象,此后程序不能再使用该对象。如果用一个指针变量pt先后指向不同的动态对象,应注意指针变量的当前指向,以免删错了对象。在执行delete运算符时,在释放内存空间之前,自动调用析构函数,完成有关善后清理工作。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号