版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第8章类和对象从简单到复杂人类发展史,是一部从简单到复杂,从容易到困难的探索历史以交通工具的生产制作为例说明。任何一个合格的木匠都能独立制作一辆马车。复杂的交通工具再优秀的工程师都无法独立生产一辆汽车甚至一辆自行车。那该怎么办呢?采用面向对象的设计思想对问题的表述从简到繁单个变量:反映无关联的属性
inta,b,c;变量的集合数组:反映同类型相关属性inta[10],b[20];结构体:反映相关属性,可以描述较复杂的事物的属性(不同类型)Structstudent{
intid;charname[20];
floatscore[5];};问题一:对变量的操作是另外定义的,与变量定义分离。问题二:对于复杂系统的描述,将有大量属性数据及其相关操作,数据与操作之间的对应关系也十分复杂属性与操作的集合--在一个类型中定义属性,同时定义与这些属性相关的操作问题三:对客观世界的描述,总是属性(数据)与性能(动作)相联系的,在计算机内部如何表达?类“时钟”类的定义classClock{private:
inthour,minute,second;public:
voidSettime(inth,intm,ints) { hour=h;minute=m;second=s; }
voidGettime(int&h,int&m,int&s) { h=hour;m=minute;s=second; }};从外界对时钟设置时间,比如钟表背面的设置按钮外界获取时钟的时间,比如钟表正面的表盘8.1面向对象程序设计方法概述对象对象的两个要素:静态特征:属性;考虑汽车有哪些属性?动态特征:行为;考虑汽车有哪些行为?一个系统的多个对象之间通过消息相互联系。考虑行驶到路口的汽车考到红灯这个信号(消息)时会产生什么样的行为?注意:汽车是一个大的对象,它是由许多更小的对象组成的,如,发动机、地盘、轮子等。封装与信息隐蔽考虑一台电视机,它里面的结构和工作原理我们知道吗?对普通的人来说,需要知道吗?封装的含义:将有关的数据和操作代码封装在一个对象中,形成一个基本的单位,各个对象之间相对独立,互不干扰。将对象中某些部分对外隐蔽,即隐蔽其内部细节,只留下少量接口,以便与外界联系,接受外界的消息。电视机的接口抽象什么是汽车?把具有轮子,能滚动前进的陆地交通工具统称为“车子”。再进一步,把用汽油发动机驱动的车子抽象为“汽车”,把用马拉的车子抽象为“马车”,用脚蹬的车子抽象为脚踏车。具有某些相同的属性和行为类与对象:类是对象的抽象,对象是类的特例,是类的具体表现形式。人小李小周…抽象的概念具体的人继承与重用现代工业高效的重要原因:重用性,一件工业产品的生产通常都不是从零开始的,总是尽可能利用前有的成果。那么软件产品呢,是不是也可以实现重用?怎么实现呢?重用要通过继承机制来实现。继承车子马车汽车脚踏车多态性考虑,停在路口的汽车和马车,当看到左转向的信号灯由红灯变为绿灯时,分别拐向机动车道和非机动车道。多态性:由继承而产生的相关的不同的类,其对象对同一消息会作出不同的响应。8.1.2面向对象程序设计的特点面向过程程序设计:围绕功能,面向函数;面向对象程序设计:围绕对象的设计,面向对象;面向对象程序设计,程序设计者的任务:设计所需的各种类和对象,即决定把哪些数据和操作封装在一起;考虑怎样向有关对象发送消息,以完成所需的任务。8.1.3类和对象的作用基于对象:Object-Based,以类和对象为基础,程序的操作时围绕对象进行的。面向对象:Object-Oriented,在基于对象的基础上,利用继承机制和多态性,实现重用性。类是所有面向对象的语言的共同特征,所有面向对象的语言都提供了这种类型一个有一定规模的C++程序是由许多类所构成的一个有一定规模的C++程序在执行时表现为许多相关的对象相互之间的作用8.2类的声明和对象的定义8.2.1类和对象的关系类与对象的关系如同结构体类型与结构体变量的关系。具体来说,就是:类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。人小李小周…抽象的概念具体的人8.2.2声明类类型类声明方法及例子如下:classClock{private:
inthour,minute,second;public:
voidSettime(inth,intm,ints) { hour=h;minute=m;second=s; }
voidGettime(int&h,int&m,int&s) { h=hour;m=minute;s=second; }};在类里包含了数据成员和操作数据成员的成员函数,实现了把数据和操作封装在一起。成员访问限定符,如不指定,则默认为private类类型的声明,一般形式如下:
class
类名{
private:私有的数据和成员函数;
public:公用的数据和成员函数;
protected: 保护的数据和成员函数;};
inthour;intminute;intsecond;DoorSettimeGettimehour,minute,secondprivatememberhourminutesecond成员访问限定符public:既可以被本类中的成员函数访问,也可以被类的作用域内的其他函数访问。private:只能被本类中的成员函数访问,在类外(友元类例外,第9章)不能被访问。(注意理解类外的含义)protected:不能被类外访问,但可以被派生类的成员函数访问。成员访问限定符的声明次序是任意的。请分析以下例子中各成员的访问属性。classClock{private:
inthour;
intminute;
intsecond;…};classClock{
inthour;private:
intminute;
intsecond;…};classClock{
inthour;public:
intminute;
intsecond;…};classClock{private:inthour;intminute;public:intsecond;…};classClock{public:
inthour;private:
intminute;public:
intsecond;…};classClock{private:
inthour,minute,second;public:
voidSettime(inth,intm,ints) {hour=h;minute=m;second=s;}
voidGettime(int&h,int&m,int&s) {h=hour;m=minute;s=second;}};私有成员,只有类内部定义的函数可以访问。公有成员,类内部、外部定义的函数都可以调用。注意理解“类外”的含义voidmain(){ Clockck;
inth,m,s; ck.Settime(8,15,23);//ck.hour=8;有语法错误吗? ck.Gettime(h,m,s); cout<<"Time:"<<h<<":"<<m<<":"<<s<<endl;}main()相对于Clock类是“外部”的,不能直接访问Clock内的私有成员,但可以通过调用Clock定义的公有函数,实现对Clock私有成员的设置与数据获取。理解“类的作用域”voidmain(){ClockCk1;//undeclaredidentifierCk1.Settime(8,12,56);}classClock{private: …public: …};//clock.hclassClock{private: …public: …};//main.cpp#include“clock.h”voidmain(){ClockCk1;//undeclaredidentifierCk1.Settime(8,12,56);}要把头文件clock.h包含进来Clock类的声明必须出现在使用之前理解类内部的作用域类是一个自成一体的“小世界”,其中的标识符(包括数据成员和成员函数)作用范围是类内部:类中的成员可以访问同一类的其它成员;类内部成员函数中定义的局部变量可以屏蔽同名的数据成员;classA{private:
intx,y;public:
voidf() {
intx;...//A::x被屏蔽 }};8.2.3定义对象的方法与使用结构体类型定义结构体变量类似//方法一classClock{private: …public: …};classClockCk1,Ck2;//方法二classClock{private: …public: …}Ck1,Ck2;//方法三class{private: …public: …}Ck1,Ck2;关于对象数据成员的初始化注意:与结构体变量初始化不同的是不能在定义对象时对对象的私有数据成员用直接赋值的形式进行初始化。对对象的私有成员的初始化要使用构造函数(第9章)来实现。classClock{private: …public: …};classClock=(10,8,24);//错误使用对象(及其成员)使用对象的成员(包括数据成员和成员函数)方法,使用成员运算符:对象.成员Clockck1,ck2;ck1.Settime(9,23,42);inthh,mm,ss;ck1.Gettime(hh,mm,ss);给对象ck1中的私有数据成员hour,minute,second赋值获取对象ck1中的私有数据成员hour,minute,second的数据通过调用类的公有成员函数访问类中的私有成员。函数参数传递使用哪种方式?8.2.4类和结构体类型的异同在C++里,从功能上说,类类型和结构体类型完全一样(在结构体里也可以定义函数),在C++保留结构仅仅是为了与C语言兼容。用struct声明的类和用class声明的类的区别:用struct声明的类,其成员访问属性默认为public,用class声明的类,其成员访问属性默认为private。一般来说,对简单的类(不包含成员函数),用struct来定义,反之,用class来定义。//没有对成员的访问属性//做显式声明,默认为publicstructStudent{intnum;
charname[20];charsex;
voiddisplay(){cout<<num<<endl;cout<<name<<endl;cout<<sex<<endl;}}//没有对成员的访问属性//做显式声明,默认为privateclassStudent{intnum;
charname[20];
charsex;
voiddisplay(){cout<<num<<endl;cout<<name<<endl;cout<<sex<<endl;}}8.3类的成员函数8.3.1成员函数的性质接口函数:需要被外界调用的成员函数,必须设置为public;工具函数:只被类中其他函数调用,不被外界调用,一般来说应该设置为private;接口函数与工具函数classClock{private:
inthour,minute,second; voidjudge(){
if(hour>23||hour<0)hour=0;
if(minute>59||minute<0)minute=0;
if(second>59||second<0)second=0; }public:
voidSettime(inth,intm,ints) {hour=h;minute=m;second=s;judge();}
voidGettime(int&h,int&m,int&s) {h=hour;m=minute;s=second;}};工具函数,只被Settime()函数调用8.3.2在类外定义成员函数成员函数可以直接在类里定义,也可以先在类里声明,然后在类外定义。classClock{private:
inthour,minute,second;public:
voidSettime(inth,intm,ints) {hour=h;minute=m;second=s;}
voidGettime(int&h,int&m,int&s);//声明};void
Clock::Gettime(int&h,int&m,int&s)//定义{h=hour;m=minute;s=second;}作用域运算符:优先级最高作用域运算符正确使用作用域运算符:在类内部声明和定义成员函数时不需要加作用域运算符;在类外部定义类的成员函数时,需要加作用域运算符;如果在外部定义函数时加了作用域运算符::,但在前面没有加类名,或者既无类名又无作用域运算符,定义的都是普通的全局函数,如:::display()或display()8.3.3inline成员函数P97内置函数(inline函数)提出原因:函数调用开销(保护现场和恢复现场)比较大。适用范围:代码简单且频繁调用的函数。(现在的编译系统已经能够识别这类函数并自动将函数设置为内置函数,并不取决与用户是否将函数声明为内置。)实现方法:在编译时直接将内置函数的代码嵌入到函数调用处。inta[1000],b[1000];…for(inti=1,sum=0;i<1000;i++) sum+=max(a[i],b[i]);intmax(inta,intb){
if(b>a)returnb;
else
returna;}类的成员函数的内置处理出发点:也是为了减小时间开销。处理方法:对于在类里面定义的成员函数,默认为内置函数,因此inline可以省略对于在类外面定义的成员函数,并不默认为inline函数,必须显式地说明。inline
voidClock::Gettime(int&h,int&m,int&s){ h=hour;m=minute;s=second;}8.3.4成员函数的存储方式声明类之后,用类去定义对象,编译系统要为对象分配存储空间。分配方法一:每定义一个对象,分别为该对象的数据和函数代码分配存储空间。缺点:浪费存储空间。(不采用)Ck1.Settime()Ck1.Gettime()Ck1.hourCk1.minuteCk1.secondCk2.Settime()Ck2.Gettime()Ck2.hourCk2.minuteCk2.second…Ck10.Settime()Ck10.Gettime()Ck10.hourCk10.minuteCk10.second注意到:同一个类的每个对象数据值不相同,但成员函数的代码是完全一样的。方法二:只用一段存储空间来存储同一个类不同对象的成员函数代码,在调用各对象的函数时,都去调用这个共用的函数代码。对象的数据成员存储在程序数据区对象的函数成员统一存储在程序代码区Settime()Gettime()Ck1.hourCk1.minuteCk1.secondCk2.hourCk2.minuteCk2.secondClockck1,ck2;//用sizeof()测试问题:当调用成员函数时,成员函数怎么知道当前操作的是哪个对象的数据?Clockck1,ck2;……Ck1.Settime(10,34,23);Ck2.Settime(23,12,54);Settime()Gettime()Ck1.hourCk1.minuteCk1.secondCk2.hourCk2.minuteCk2.second调用(10,34,23)调用(23,12,54)使用哪一套?需要有一个参数来表示当前操作的是哪个对象this指针this指针(P281)在对象调用成员函数时,除了传递函数参数外,还传递一个隐含的指针--this指针,指向对象本身。当调用ck1的成员函数,this指针就指向ck1,当调用ck2的成员函数,this指针就指向ck2。在成员函数中,所有对数据成员的访问都会(隐含地)加上一个this指针:hour this->hourminutethis->minutesecondthis->secondclassClock{private:
inthour,minute,second;public:
voidSettime(inth,intm,ints) { this->hour=h; this->minute=m; this->second=s;}
voidGettime(int&h,int&m,int&s);//声明};void
Clock::Gettime(int&h,int&m,int&s)//定义{h=hour;m=minute;s=second;}classClock{private:
inthour,minute,second;public:
voidSettime(inth,intm,ints) { hour=h; minute=m; second=s;}
voidGettime(int&h,int&m,int&s);//声明};void
Clock::Gettime(int&h,int&m,int&s)//定义{h=hour;m=minute;s=second;}Settime()Ck1.hourCk1.minuteCk1.secondCk2.hourCk2.minuteCk2.second调用(10,34,23,this(ck2))调用(23,12,54,this(ck1))……Ck1.Settime(23,12,54);Ck2.Settime(10,34,23);8.4对象成员的引用通过对象名和成员运算符访问对象中的成员通过指向对象的指针访问对象中的成员通过对象的引用变量访问对象中的成员例如:stud1.num=1001;//假设num已定义为公用的整型数据成员例如:class
Time{public://数据成员是公用的
inthour;
intminute;};Timet,*p;//定义对象t和指针变量pp=&t;//使p指向对象tcout<<p->hour;//输出p指向的对象中的成员hour例如:class
Time{public://数据成员是公用的
inthour;
intminute;};Timet1;//定义对象t1Time&t2=t1;//定义Time类引用变量t2,并使之初始化为t1cout<<t2.hour;//输出对象t1中的成员hour说明:同一类型的对象可整体赋值,但使用要慎重(P291介绍对象拷贝)。intmain(){ClockCk1,Ck2;Ck1.Settime(8,12,20);Ck2=Ck1;//请慎重使用
inth,m,s;Ck2.Gettime(h,m,s);cout<<"hour:"<<h<<"minute:"<<m<<"second:"<<s<<endl;
return0;}8.5类的封装性和信息隐蔽面向对象程序设计方法中,封装性和信息隐蔽的目的:为保证安全性,尽可能不让类外的函数直接使用类的数据成员;为保密起见,尽可能不公开成员函数的代码;为使用方便和减小开销,在使用类时只需加载尽可能少的文件,和避免重复加载。实现的原则:公用接口和私有实现的分离类声明和成员函数定义的分离8.5.1公用接口与私有实现的分离一般把类的数据成员设置为私有,不允许外界直接访问数据成员,公用成员函数充当使用类的公用接口。公用成员函数的代码一般是不公开的,其中实现的细节是隐蔽的,称为私有实现。
inthour;intminute;intsecond;DoorSettimeGettimehour,minute,secondprivatememberhms8.5.2类声明和成员函数定义的分离出发点:把类的声明和成员函数的实现分别放在不同的文件里。头文件的处理:如果在程序中需要使用到该类,只要把头文件包含进来就可以了。实现文件的处理:编译成目标文件一次性加载进来。//student.hstructStudent{public:
voiddisplay();private:
intnum;
charname[20];
charsex;}//student.cpp#include<iostream>#include"student.h“usingnamespacestd;voidStudent::display(){cout<<"num:"<<num<<endl;cout<<"name:"<<name<<endl;cout<<"sex:"<<sex<<endl;}//main.cpp#include<iostream>#include"student.h"usingnamespacestd;voidmain(){Studentstud;stud.display();
return0;}使用类的接口文件包含预处理中,用尖括号(<>)和双撇号(“”)的区别(P130):用尖括号:编译系统到系统目录中寻找要包含的文件。系统目录就是安装C++系统的目录。双撇号:编译系统先到指定目录中去找要包含的文件,如果没有指定目录,则在当前目录下找;如果找不到,再到系统目录下去找。//main.cpp#include<iostream>#include<student.h>//错误voidmain(){Studentstud;stud.display();return0;}类库类库:把若干个常用的功能相近的类声明集中在一起,形成类库。C++编译器提供的标准类库;如标准输入流对象cin就是在标准类库中定义的。还有常用的数学函数也是由标准类库提供的,其声明在math.h头文件中给出。用户根据自己的需要或出于商业的目的开发的用户类库,称为自定义类库。8.5.3对象、方法、消息类的成员函数:方法调用成员函数的程序语句:消息inth,m,s;Ck1.Gettime(h,m,s);给对象Ck1发出一个消息,通知它执行其中的Gettime方法,得到其私有成员hour,minute,second,保存到变量h,m,s里。8.6类和对象的简单应用举例书上的例子例8.1,类Time不含函数成员。例8.2程序(a):多个Time对象,在主函数中依次对其成员进行赋值,然后输出;程序(b):在主函数中定义set_time函数,实现对Time对象成员的赋值,定义show_time函数,实现输出Time对象的成员;程序(c):set_time函数改为通过参数实现对Time对象成员的赋值,并且是默认参数。例8.3,用含成员函数的Time类实现例8.2例8.4,用类的方法实现找出一个整数数组中的元素的最大值。课后习题6需要求3个长方体的体积,请编写一个基于对象的程序。对象的数据成员包括length,width,height。要求用成员函数实现以下功能:由键盘分别输入3个长方体的长、宽、高;计算长方体的体积;输出3个长方体的体积。分析:类的3个数据成员都是私有的;成员函数get_value实现从键盘上输入3个成员数据;成员函数volume实现计算长方体的体积;成员函数display实现输出长方体的体积;classBox{public:
voidget_value();
floatvolume();
voiddisplay();private:
floatlengh,width,height;};voidBox::get_value(){cout<<"pleaseinputlengh,width,height:";cin>>lengh;cin>>width;cin>>height;}floatBox::volume(){return(lengh*width*height);}voidBox::display(){cout<<volume()<<endl;}intmain(){Boxbox1,box2,box3;box1.get_value();cout<<"volmueofbax1is";box1.display();box2.get_value();cout<<"volmueofbax2is";box2.display();box3.get_value();cout<<"volmueofbax3is";box3.display();
return0;}改进:再定义一个成员,记录长方体的体积classBox{public:
voidget_value();
floatvolume();
voiddisplay();private:
floatlengh,width,height;
floatvol;};voidBox::get_value(){cout<<"pleaseinputlengh,width,height:";cin>>lengh;cin>>width;cin>>height;}floatBox::volume(){vol=lengh*width*height;}voidBox::display(){cout<<vol<<endl;}Person类新建控制台工程(Win32ConsoleApplication)头文件person.h#include<iostream.h>#include<string.h>classPerson{private:
charName[20];
unsignedAge;
charSex;public:
voidRegister(constchar*,int,char);//为数据成员赋值
voidGetName(char*na) //取得数据成员Name {strcpy(na,Name);};
intGetAge() //取得数据成员Age {return(Age);};
charGetSex(); //取得数据成员sex {return(Sex);
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年度影视作品改编权授权合同
- 2024年度艺术品交易平台运营授权合同
- 2024年度甲方委托乙方进行工厂培训设施建设与运营的承包合同
- 2024年度货物买卖合同(含退换货条款)
- 教育培训资源共享服务平台建设与运营合同
- 技术培训服务合同
- 托管教师聘用合同
- 市场场地租赁合同
- 软件开发合同终止协议书
- IT外包服务管理和咨询合同
- Honda-Special-Requirement本田的特殊要求-课件
- 2021-2022学年高中英语北师大版(2019)选择性必修第二册Units 4-6 全册单词表
- 道格拉斯公司销售数据决策案例分析课件
- 北理c语言上机答案(全)
- 水泵各部分结构及原理介绍课件
- 电工基础(周绍敏主编)-参考答案
- 双向情感障碍
- 统编语文教材的主要特点和教学建议(课堂PPT)课件
- 胃溃疡 演示文稿课件
- 胃肠镜检查前后注意事项课件-002
- ESD的防护常识幻灯片
评论
0/150
提交评论