面向对象编程技术第四章_第1页
面向对象编程技术第四章_第2页
面向对象编程技术第四章_第3页
面向对象编程技术第四章_第4页
面向对象编程技术第四章_第5页
已阅读5页,还剩60页未读 继续免费阅读

下载本文档

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

文档简介

面向对象编程技术第四章第1页,共65页,2023年,2月20日,星期四一、类与对象类概述类是具有相同属性和行为的一组对象的抽象集合,为该类的全部对象提供了统一的抽象描述,包括属性和行为两个主要部分。利用类可以实现数据的封装、隐藏、继承与派生。利用类易于编写大型复杂程序,其模块化程度比C中采用函数更高。慢慢体会…第2页,共65页,2023年,2月20日,星期四类是一种用户自定义类型,声明形式:class类名{

public:公有成员(外部接口)private:私有成员protected:保护型成员}2.类的定义:第3页,共65页,2023年,2月20日,星期四时钟类的成员(数据成员与函数成员声明)classClock{private:intHour,Minute,Second;public:

voidSetTime(intNewH,intNewM,

intNewS);

voidShowTime();

};成员函数数据成员第4页,共65页,2023年,2月20日,星期四voidClock::SetTime(intNewH,intNewM,intNewS){Hour=NewH;Minute=NewM;Second=NewS;}voidClock::ShowTime(){cout<<Hour<<":"<<Minute<<":"<<Second;}时钟类的函数成员(定义部分)第5页,共65页,2023年,2月20日,星期四说明:关键字public后面声明公有类型成员它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数关键字private后面声明私有类型成员允许本类中的函数访问,类外部的任何函数都不能访问。紧跟在类名称的后面声明私有成员,关键字private可省略(不提倡)第6页,共65页,2023年,2月20日,星期四说明:保护类型与private类似,其差别表现在继承与派生时对派生类的影响不同,在第七章介绍。下页例子第7页,共65页,2023年,2月20日,星期四classcircle{public:circle::circle(intr){radius=r;}intarea(){return(int)3.14*radius*radius;

}voidcircle_prt(){cout<<"theprivateradiusis:"<<radius<<endl;}private:intradius;

};voidmain(){circlecircle1(1),circle2(3);

cout<<"theprivateradiusis:"<<circle1.radius<<endl;circle1.circle_prt();Circle2.circle_prt();}ERROR!不允许访问私有数据!如何解决?OK构造函数,后面介绍另一例子第8页,共65页,2023年,2月20日,星期四说明:数据成员:1.与一般的变量声明相同,但需要将它放在类的声明体中。2.不能在定义时初始化赋值定义成员时并不分配存储空间,如inthour=0

函数成员:1.成员函数分类(1)构造函数与析构函数(2)其他成员函数2.在类中说明原形,在类外给出函数体实现,并在函数名前使用类名加以限定。也可以直接在类中给出函数体允许声明重载函数和带缺省形参值的函数建议定义在类外第9页,共65页,2023年,2月20日,星期四3.对象的定义类的对象是该类的实例化,即类类型的变量。声明形式:类名对象名;例:ClockmyClock;第10页,共65页,2023年,2月20日,星期四4.类、对象中成员的访问方式类中成员互访直接使用成员名类外访问使用“对象名.成员名”方式访问public属性的成员使用“对象名指针->成员名”方式访问public属性的成员返回第11页,共65页,2023年,2月20日,星期四二、构造函数与析构函数构造函数名与类名相同构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态。在对象创建时由系统自动调用。如果程序中未声明,则系统自动产生出一个缺省形式的构造函数1.构造函数定义及使用第12页,共65页,2023年,2月20日,星期四构造函数举例classcircle{public:

intradius;intarea();circle(intr);intarea(intr);};circle::circle(intr){radius=r;}intcircle::area(){return(int)3.14*radius*radius;}voidmain(){circlecircle1(5);cout<<"thecircle'sareais";cout<<circle1.area()<<endl;}定义部分第13页,共65页,2023年,2月20日,星期四构造函数与类同名不能指定返回值类型可以是重载函数可以是内联函数如无自定义构造函数,C++系统自动产生空的的构造函数如构造函数带有参数,则在定义对象时必须带上相同类型的实参通过定义类的实例-对象,只分配数据成员空间,共享类的代码空间注意:第14页,共65页,2023年,2月20日,星期四析构函数名:~类名完成对象被删除前的一些清理工作。在对象的生存期结束的时刻系统自动调用它,然后再释放此对象所属的空间。如果程序中未声明析构函数,编译器将自动产生一个缺省的析构函数。析构函数不带任何参数2.析构函数定义及使用请关注后面的内容!第15页,共65页,2023年,2月20日,星期四析构函数举例classPoint{public:Point(intxx,intyy);

~Point();//...其它函数原形private:intX,intY;};包含:deleteAdeleteB…第16页,共65页,2023年,2月20日,星期四注意命名方式一般类中设计有动态对象,则要设计析构函数析构函数不带任何参数第17页,共65页,2023年,2月20日,星期四课堂练习(5分钟):1.定义一个表述圆的类(数据成员和函数成员),并提供相应的方法2.定义一个表述人的类,(数据成员和函数成员),并提供相应的方法体会面向对象的编程的特点第18页,共65页,2023年,2月20日,星期四3.内联成员函数为了提高运行时的效率,对于较简单的函数可以声明为内联形式。内联函数体中不要有复杂结构(如循环语句和switch语句)。类中声明内联成员函数的方式:将函数体放在类的声明中。使用inline关键字。内联函数两种声明方式:显示与隐式隐式:直接定义在类主体内显示:定义在类主体外,用inline说明请看下页注意何时采用?第19页,共65页,2023年,2月20日,星期四classPoint{public:

voidInit(intinitX,intinitY){X=initX;Y=initY;}intGetX(){returnX;}intGetY(){returnY;}private:intX,Y;};classPoint{public:voidInit(intinitX,intinitY);intGetX();intGetY();private:intX,Y;};inlinevoidPoint::Init(intinitX,intinitY){X=initX;Y=initY;}inlineintPoint::GetX(){returnX;}隐式: 显式:第20页,共65页,2023年,2月20日,星期四

当构造函数的参数为自身类对象的引用时,这个构造函数称为拷贝构造函数.

拷贝构造函数的功能是用一个已有对象初始化一个正在建立的同类对象.4.拷贝构造函数已存在对象新对象克隆第21页,共65页,2023年,2月20日,星期四拷贝构造函数在以下三种情况下会被调用:⑴当用类的一个对象去初始化该类的另一个对象时;⑵如果函数的形参是类对象,调用函数进行形参和实参结合时;⑶如果函数的返回值是类对象,函数调用完成返回时。何时需要它?第22页,共65页,2023年,2月20日,星期四定义:class

类名{public:类名(形参);//构造函数类名(类名&对象名);//拷贝构造函数...};类名::类名(类名&对象名)//拷贝构造函数的实现{函数体}第23页,共65页,2023年,2月20日,星期四Pointa=a1;//拷贝构造函数

等价于Pointa(a1);//可以改成这种形式

Point::Point(Point&p){X=p.X;Y=p.Y;cout<<"拷贝构造函数被调用"<<endl;}classPoint{public:Point(intxx=0,intyy=0){X=xx;Y=yy;}

Point(Point&p);intGetX(){returnX;}intGetY(){returnY;}private:intX,Y;};请看下页第24页,共65页,2023年,2月20日,星期四当用类的一个对象去初始化该类的另一个对象时系统自动调用它实现拷贝赋值。voidmain(void){PointA(1,2);PointB(A);//拷贝构造函数被调用cout<<B.GetX()<<endl;}情形之一第25页,共65页,2023年,2月20日,星期四若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数。例如:voidfun1(Pointp){cout<<p.GetX()<<endl;}voidmain(){PointA(1,2);fun1(A);//调用拷贝构造函数}

情形之二第26页,共65页,2023年,2月20日,星期四当函数的返回值是类对象时,系统自动调用拷贝构造函数。例如:Pointfun2(){PointA(1,2);returnA;//调用拷贝构造函数}voidmain(){PointB;B=fun2();}情形之三要看明白书上的例子返回第27页,共65页,2023年,2月20日,星期四三、面向对象的基本特点抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的过程。数据抽象:描述某类对象的属性或状态(对象相互区别的物理量)。代码抽象:描述某类对象的共有的行为特征或具有的功能。-之抽象?如何实现抽象通过类的定义。第28页,共65页,2023年,2月20日,星期四三、面向对象的设计思想层层分类,使概念逐渐细化,即具体化。例如,生物分为动物和植物,动物又分为脊椎动物和无脊椎动物,脊椎动物包括哺乳动物,哺乳动物又分为猫、狗……,等等-之分类回顾第29页,共65页,2023年,2月20日,星期四三、面向对象的设计思想将抽象出的数据成员、代码成员相结合,将它们视为一个整体。增强安全性和简化编程,不必了解具体的实现细节,只需要通过外部接口,以特定的访问权限,来使用类的成员。实现封装:类定义中的{}-之封装在设计者允许的权限下第30页,共65页,2023年,2月20日,星期四三、面向对象的设计思想子类与父类子类继承父类所有的属性、方法,并可定义自己的特有属性与方法提高软件开发效率,为软件复用提供强有力的支持多种继承方式:公有、私有、保护;单继承、多继承-之继承第31页,共65页,2023年,2月20日,星期四三、面向对象的设计思想-之多态定义:指类具有相似功能的不同函数使用同一个名称来实现如:1.运算符重载2.函数重载3.虚函数

…慢慢领会…第32页,共65页,2023年,2月20日,星期四插入语学习复杂、严密的C++语法体系C++既考虑设计理念的先进性,又兼顾程序执行的效率!理解、领会、运用其中的优秀的面向对象程序设计、分析思想!返回是否感觉有点烦!第33页,共65页,2023年,2月20日,星期四四、类的组合类中的成员数据是另一个类的对象可以在已有的抽象的基础上实现更复杂的抽象注意是对象第34页,共65页,2023年,2月20日,星期四例:classPoint{private:floatx,y;//点的坐标

public:Point(floath,floatv);//构造函数

floatGetX(void);//取X坐标

floatGetY(void);//取Y坐标

voidDraw(void);//在(x,y)处画点};//...函数成员部分,略第35页,共65页,2023年,2月20日,星期四classLine{private:pointp1,p2;//线段的两个端点public:Line(Pointa,Pointb);//构造函数VoidDraw(void);//画出线段};//...函数的实现略第36页,共65页,2023年,2月20日,星期四1.如何设计组合类的构造函数?原则:不仅要负责对本类中的基本类型成员数据赋初值,也要对对象成员初始化。声明形式:类名::类名(形参,本类成员形参):内嵌对象1(参数),内嵌对象2(参数),......{本类初始化}注意否则可能是一个不确定的值第37页,共65页,2023年,2月20日,星期四2.组合类的构造函数调用构造函数调用顺序:若调用缺省构造函数(即无形参的),则内嵌对象的初始化也将调用相应的缺省构造函数。内嵌对象的构造函数内嵌对象是客人;声明顺序调用本类的构造函数调用本类的析构函数内嵌对象的析构函数构造:析构:穿衣服与脱衣服第38页,共65页,2023年,2月20日,星期四classPoint //Point类声明{public: Point(intxx=0,intyy=0){X=xx;Y=yy;cout<<"point的构造函数被调用"<<endl;} Point(Point&p); intGetX(){returnX;} intGetY(){returnY;}private: intX,Y;};Point::Point(Point&p) //拷贝构造函数的实现{ X=p.X; Y=p.Y; cout<<"Point拷贝构造函数被调用"<<endl;}第39页,共65页,2023年,2月20日,星期四classLine //Line类的声明{public: //外部接口 Line(Pointxp1,Pointxp2); Line(Line&); doubleGetLen(){returnlen;}private: //私有数据成员 Pointp1,p2; //Point类的对象p1,p2 doublelen; };//组合类的构造函数Line::Line(Pointxp1,Pointxp2):p1(xp1),p2(xp2){ cout<<"Line构造函数被调用"<<endl; doublex=double(p1.GetX()-p2.GetX()); doubley=double(p1.GetY()-p2.GetY()); len=sqrt(x*x+y*y);}第40页,共65页,2023年,2月20日,星期四Line::Line(Line&Seg):p1(Seg.p1),p2(Seg.p2){ cout<<"Line拷贝构造函数被调用"<<endl; len=Seg.len;}//主函数voidmain(){ Pointmyp1(1,1),myp2(4,5); //建立Point类的对象 Lineline(myp1,myp2); //建立Line类的对象 Lineline2(line); //利用拷贝构造函数建立一个新对象 cout<<"Thelengthofthelineis:"; cout<<line.GetLen()<<endl; cout<<"Thelengthoftheline2is:"; cout<<line2.GetLen()<<endl;}第41页,共65页,2023年,2月20日,星期四第42页,共65页,2023年,2月20日,星期四例2:整体类部件子类1部件子类2部件子类n……代码框架第43页,共65页,2023年,2月20日,星期四classWhole//整体类{public:Whole();Whole(inti,intj,intk);~Whole();voidPrint();private:Partone;Parttwo;intdate;};classPart//部件类{public:Part();Part(inti);~Part();voidPrint();private:intval;};下页定义整体类的构造函数第44页,共65页,2023年,2月20日,星期四Whole::Whole(){date=0;}Whole::Whole(inti,intj,intk):two(i),one(j),date(k){...}//...其它函数的实现略返回第45页,共65页,2023年,2月20日,星期四五、前向引用声明类应该先声明,后使用如果需要在某个类的声明之前,引用该类,则应进行前向引用声明。前向引用声明只为程序引入一个标识符,没有具体定义,不能使用该类的具体细节(如对象)。具体参考教材P112-113第46页,共65页,2023年,2月20日,星期四前向引用声明举例:classB;//前向引用声明classA{public:voidf(Bb);};classB{public:voidg(Aa);};返回第47页,共65页,2023年,2月20日,星期四template<模板参数表>类声明六、类模板使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括系统预定义的和用户自定义的)目的:格式:template<typename标示符>函数模板定义比较第48页,共65页,2023年,2月20日,星期四书上的例子:请先阅读5minsstructstudent{ intid; floatgpa;};template<classT>classstore{private: Titem; inthavevalue; intflag;public: store(void); Tgetelem(void); voidputelem(Tx);};template<classT>store<T>::store():havevalue(1),flag(99){}template<classT>Tstore<T>::getelem(void){ if(havevalue==0) {cout<<"noitempresent!"<<endl; exit(0); } else {cout<<"thehavevalueis:"<<havevalue<<endl; cout<<"theflagis:"<<flag<<endl; returnitem; }}这儿构造函数定义时,初始化其它数据成员可以改成class吗?返回第49页,共65页,2023年,2月20日,星期四template<classT>voidstore<T>::putelem(Tx){havevalue++;item=x;}voidmain(){studentg={1000,23};store<int>s1,s2;s1.putelem(3);s2.putelem(7);cout<<s1.getelem()<<""<<s2.getelem()<<endl;返回第50页,共65页,2023年,2月20日,星期四classcircle{public:inthavevalue;circle(intr);intarea(){return(int)3.14*radius*radius;}voidcircle_prt(){cout<<"theprivateradiusis:"<<radius<<endl;}private:intradius;};circle::circle(intr):havevalue(3){radius=r;}voidmain(){circlecircle1(1);circle*cp;cp=&circle1;cout<<"havevalue=:“;cout<<circle1.havevalue<<endl;circle1.circle_prt();cout<<"outbypointer:“;cout<<cp->havevalue<<endl;cout<<"outtheprivatedata”;cout<<circle1.radius<<cp->radius;//error}初始化禁止访问私有数据返回返回返回第51页,共65页,2023年,2月20日,星期四七、面向对象标记两种方法UML:统一建模语言

专业的面向对象建模语言,功能强大较复杂

Coad/Yourdon类图描述

简单明晰难以描述成员的访问控制第52页,共65页,2023年,2月20日,星期四UML对象名数据成员函数成员类名数据成员函数成员Coad/Yourdon消息继承包含返回第53页,共65页,2023年,2月20日,星期四要点回顾1.类与对象的概念2.基本类的定义与使用1.类定义的格式:classname{…}2.访问控制3.对象创建与撤销1.类内、类外的理解2.数据成员与函数成员的区别3.public与private:公共接口与隐藏1.构造、析构函数:公有、无返回值2.拷贝构造函数3.组合类1.定义:类中内嵌对象

?问:内嵌类的定义是组合类吗2.组合类构造与析构:调用顺序4.类模板1.设计思想:数据处理的通用性,参数化程序设计2.适用范围:普通数据类型、自定义数据类型、类3.注意事项:成员函数是模板函数、代码要通用返回第54页,共65页,2023年,2月20日,星期四ClassA{public:inta,b,c;……private:intx,y,z;……}返回Aa1,a2,a3;第55页,共65页,2023年,2月20日,星期四ClassA{public:inta,b,c;……private:intx,y,z;……}公共接口内部数据,隐私返回第56页,共65页,2023年,2月20日,星期四1.构造函数与析构函数的功能?2.默认构造函数:系统可以产生缺省的构造函数与析构函数3.构造函数可以重载,析构函数可以重载吗?返回第57页,共65页,2023年,2月20日,星期四为什么需要拷贝构造函数?格式:类名(类名&对象名){……}那些情形调用拷贝构造函数?1.用同类对象初始化另一个对象2.用于对象参数传递3.函数的返回值是对象?如何理解返回第58页,共65页,2023年,2月20日,星期四classouter{public:inta;classinner{public: intb; inner(){cout<<"runtheinnerconstructor"<<endl; }voidshow(){cout<<"thedataofinneris:"<<b<<endl; } }inn;

温馨提示

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

评论

0/150

提交评论