面向对象编程技术第四章课件.ppt
第四章 类与对象1类和对象类和对象2构造函数与析构函数构造函数与析构函数3面向对象的基本特点面向对象的基本特点4类的组合类的组合5前向引用说明前向引用说明6类模板类模板/以后介绍以后介绍7面向对象标记面向对象标记8要点回顾要点回顾认识事物的认识事物的规律:由简规律:由简单到复杂单到复杂!顺顺序体现第三版序体现第三版本改进了本改进了一、类与对象1.类概述类概述1.类是具有相同属性和行为的一组对象的抽象集合,为该类的全部对象提供了统一的抽象描述,包括属性和行为两个主要部分。2.利用类可以实现数据的封装、隐藏、继承与派生。3.利用类易于编写大型复杂程序,其模块化程度比C中采用函数更高。慢慢体会慢慢体会类是一种用户自定义类型,声明形式:class 类名 public:公有成员(外部接口)private:私有成员 protected:保护型成员2.类的定义:类的定义:时钟类的成员(数据成员与函数成员声明)class Clockprivate:int Hour,Minute,Second;public:void SetTime(int NewH,int NewM,int NewS);void ShowTime();成员函数成员函数数据成员数据成员void Clock:SetTime(int NewH,int NewM,int NewS)Hour=NewH;Minute=NewM;Second=NewS;void Clock:ShowTime()coutHour:Minute:Second;时钟类的函数成员(定义部分)说明说明:1.关键字public后面声明公有类型成员 它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数2.关键字private后面声明私有类型成员 允许本类中的函数访问,类外部的任何函数都不能访问。紧跟在类名称的后面声明私有成员,关键字private可省略(不提倡)说明:3.保护类型与private类似,其差别表现在继承与派生时对派生类的影响不同,在第七章介绍。下页下页 例子例子class circle public:circle:circle(int r)radius=r;int area()return(int)3.14*radius*radius;void circle_prt()coutthe private radius is:radiusendl;private:int radius;void main()circle circle1(1),circle2(3);coutthe private radius is:circle1.radius成员名”方式访问 public 属性的成员返返 回回二、构造函数与析构函数构造函数名与类名相同构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态。在对象创建时由系统自动调用。如果程序中未声明,则系统自动产生出一个缺省形式的构造函数1.构造函数构造函数定义及使用定义及使用构造函数举例class circle public:int radius;int area();circle(int r);int area(int r);circle:circle(int r)radius=r;int circle:area()return(int)3.14*radius*radius;void main()circle circle1(5);coutthe circles area is;coutcircle1.area()endl;定义部分定义部分1.构造函数与类同名2.不能指定返回值类型不能指定返回值类型3.可以是重载函数4.可以是内联函数5.如无自定义构造函数,C+系统自动产生空的的构造函数6.如构造函数带有参数,则在定义对象时必须带上相同类型的实参7.通过定义类的实例对象,只分配数据成员空间,共享类的共享类的代码空间代码空间注意:注意:析构函数名:类名完成对象被删除前的一些清理工作。在对象的生存期结束的时刻系统自动调用它,然后再释放此对象所属的空间。如果程序中未声明析构函数,编译器将自动产生一个缺省的析构函数。析构函数不带任何参数2.析构函数析构函数定义及使用定义及使用请关注后请关注后面的内容!面的内容!析构函数举例class Point public:Point(int xx,int yy);Point();/.其它函数原形 private:int X,int Y;包含:delete A delete B 注意1.命名方式2.一般类中设计有动态对象,则要设计析构函数3.析构函数不带任何参数课堂练习课堂练习(5分钟分钟):1.定义一个表述圆的类(数据成员和函数成员),并提供相应的方法2.定义一个表述人的类,(数据成员和函数成员),并提供相应的方法体会面向对象的编程的特点3.内联成员函数为了提高运行时的效率,对于较简单的函数可以声明为内联形式。内联函数体中不要有复杂结构(如循环语句和switch语句)。类中声明内联成员函数的方式:将函数体放在类的声明中。使用inline关键字。内联函数两种声明方式:显示与隐式隐式:直接定义在类主体内显示:定义在类主体外,用inline 说明请看请看 下页下页注意何时采用注意何时采用?class Point public:void Init(int initX,int initY)X=initX;Y=initY;int GetX()return X;int GetY()return Y;private:int X,Y;class Point public:void Init(int initX,int initY);int GetX(););int GetY(););private:int X,Y;inline void Point:Init(int initX,int initY)X=initX;Y=initY;inline int Point:GetX()return X;隐式:隐式:显式:显式:当构造函数的参数为自身类对象的引用参数为自身类对象的引用时,这个构造函数称为拷贝构造函数.拷贝构造函数的功能是用一个已有对象初始化一个正在建立的同类对象.4.拷贝构造函数已存在对象已存在对象新对象新对象克隆克隆拷贝构造函数在以下三种情况下会被调用:拷贝构造函数在以下三种情况下会被调用:当用类的一个对象去初始化该类的另一个对象时;如果函数的形参是类对象类对象,调用函数进行形参和实参结合时;如果函数的返回值返回值是类对象,函数调用完成返回完成返回时。何时需要何时需要它?它?定义:class 类名 public:类名(形参);/构造函数 类名(类名类名&对象名对象名);/拷贝构造函数 .;类名:类名(类名&对象名)/拷贝构造函数的实现 函数体 Point a=a1;/拷贝构造函数 等价于等价于Point a(a1);/可以改成这种形式 Point:Point(Point&p)X=p.X;Y=p.Y;cout拷贝构造函数被调用endl;class Point public:Point(int xx=0,int yy=0)X=xx;Y=yy;Point(Point&p);int GetX()return X;int GetY()return Y;private:int X,Y;请看请看 下页下页当用类的一个对象去初始化该类的另一个对象时系统自动调用它实现拷贝赋值。void main(void)Point A(1,2);Point B(A);/拷贝构造函数被调用拷贝构造函数被调用 coutB.GetX()endl;情形之一情形之一 若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数。例如:void fun1(Point p)coutp.GetX()endl;void main()Point A(1,2);fun1(A);/调用拷贝构造函数调用拷贝构造函数 情形之二情形之二 当函数的返回值是类对象时,系统自动调用拷贝构造函数。例如:Point fun2()Point A(1,2);return A;/调用拷贝构造函数调用拷贝构造函数void main()Point B;B=fun2();情形之三情形之三要看明白书上要看明白书上的例子的例子返返 回回三、面向对象的基本特点抽象抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的过程。数据抽象:描述某类对象的属性或状态(对象相互区别的物理量)。代码抽象:描述某类对象的共有的行为特征或具有的功能。之抽象之抽象?如何实现抽象如何实现抽象通过类的定义。三、面向对象的设计思想层层分类层层分类,使概念逐渐细化,即具体化。例如,生物分为动物和植物,动物又分为脊椎动物和无脊椎动物,脊椎动物包括哺乳动物,哺乳动物又分为猫、狗,等等之分类之分类回回 顾顾三、面向对象的设计思想将抽象出的数据成员、代码成员相结合,将它们视为一个整体。1.增强安全性和简化编程,不必了解具体的实现细节,只需要通过外部接口,以特定的访问权限,来使用类的成员。2.实现封装:类定义中的 之封装之封装在设计者允许在设计者允许的权限下的权限下三、面向对象的设计思想子类与父类1.子类继承父类所有的属性、方法,并可定义自己的特有属性与方法2.提高软件开发效率,为软件复用提供强有力的支持3.多种多种继承方式:公有、私有、保护;单继承、多继承之继承之继承三、面向对象的设计思想之多态之多态定义:指类具有相似功能的不同函数使用同一个名称 来实现如:1.运算符重载 2.函数重载 3.虚函数 慢慢领会慢慢领会插入语插入语学习复杂、严密的C+语法体系C+既考虑设计理念的先进性,又兼顾程序执行的效率!理解、领会、运用其中的优秀的面向对象程序设计、分析思想!返返 回回是否感觉有是否感觉有点烦!点烦!四、类的组合类中的成员数据是另一个类的对象类的对象可以在已有的抽象的基础上实现更复杂的抽象注意是对象注意是对象例例:class Point private:float x,y;/点的坐标 public:Point(float h,float v);/构造函数 float GetX(void);/取X坐标 float GetY(void);/取Y坐标 void Draw(void);/在(x,y)处画点;/.函数成员部分,略class Line private:point p1,p2;/线段的两个端点 public:Line(Point a,Point b);/构造函数 Void Draw(void);/画出线段;/.函数的实现略函数的实现略1.如何设计组合类的构造函数?如何设计组合类的构造函数?原则:原则:不仅要负责对本类中的基本类型成员数据赋初值,也要对对象成员初始化。声明形式:声明形式:类名:类名(形参,本类成员形参):内嵌对象1(参数),内嵌对象2(参数),.本类初始化 注意注意否则可能是否则可能是一个不确定一个不确定的值的值2.组合类的构造函数调用组合类的构造函数调用构造函数调用顺序:构造函数调用顺序:若调用缺省构造函数(即无形参的),则内嵌对象的初始化也将调用相应的缺省构造函数。内嵌对象的构造函数内嵌对象是客人;内嵌对象是客人;声明顺序声明顺序调用本类的构造函数调用本类的析构函数内嵌对象的析构函数构造:构造:析构:析构:穿衣服与穿衣服与脱衣服脱衣服class Point/Point类声明public:Point(int xx=0,int yy=0)X=xx;Y=yy;coutpoint 的构造函数被调用endl;Point(Point&p);int GetX()return X;int GetY()return Y;private:int X,Y;Point:Point(Point&p)/拷贝构造函数的实现X=p.X;Y=p.Y;coutPoint拷贝构造函数被调用endl;class Line/Line类的声明public:/外部接口Line(Point xp1,Point xp2);Line(Line&);double GetLen()return len;private:/私有数据成员Point p1,p2;/Point类的对象p1,p2double len;/组合类的构造函数Line:Line(Point xp1,Point xp2):p1(xp1),p2(xp2)coutLine构造函数被调用endl;double x=double(p1.GetX()-p2.GetX();double y=double(p1.GetY()-p2.GetY();len=sqrt(x*x+y*y);Line:Line(Line&Seg):p1(Seg.p1),p2(Seg.p2)coutLine拷贝构造函数被调用endl;len=Seg.len;/主函数void main()Point myp1(1,1),myp2(4,5);/建立Point类的对象Line line(myp1,myp2);/建立Line类的对象Line line2(line);/利用拷贝构造函数建立一个新对象coutThe length of the line is:;coutline.GetLen()endl;coutThe length of the line2 is:;coutline2.GetLen()endl;例例2:整体类整体类部部件件子子类类1部部件件子子类类2部部件件子子类类n代码框架代码框架class Whole/整体类整体类public:Whole();Whole(int i,int j,int k);Whole();void Print();private:Part one;Part two;int date;class Part /部件类部件类public:Part();Part(int i);Part();void Print();private:int val;下页定义整体类的构造函数下页定义整体类的构造函数Whole:Whole()date=0;Whole:Whole(int i,int j,int k):two(i),one(j),date(k)./.其它函数的实现略其它函数的实现略返返 回回五、前向引用声明五、前向引用声明类应该先声明,后使用如果需要在某个类的声明之前,引用该类,则应进行前向引用声明。前向引用声明只为程序引入一个标识符,没有具体定义,不能使用该类的具体细节(如对象)。具体参考教材P112113前向引用声明举例前向引用声明举例:class B;/前向引用声明前向引用声明class A public:void f(B b);class B public:void g(A a);返返 回回template 类声明六、类模板六、类模板 使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括系统预定义的和用户自定义的)目的目的:格式:格式:template 函数模板定义比较比较书上的例子:请先阅读5minsstruct studentint id;float gpa;template class store private:T item;int havevalue;int flag;public:store(void);T getelem(void);void putelem(T x);templatestore:store():havevalue(1),flag(99)templateT store:getelem(void)if(havevalue=0)coutno item present!endl;exit(0);elsecoutthe havevalue is:havevalueendl;coutthe flag is:flagendl;return item;这儿这儿构造函数定义时,初始化其它数据成员构造函数定义时,初始化其它数据成员可以改成可以改成class吗吗?返返 回回templatevoid store:putelem(T x)havevalue+;item=x;void main()student g=1000,23;stores1,s2;s1.putelem(3);s2.putelem(7);couts1.getelem()s2.getelem()endl;返返 回回class circle public:int havevalue;circle(int r);int area()return(int)3.14*radius*radius;void circle_prt()coutthe private radius is:radiusendl;private:int radius;circle:circle(int r):havevalue(3)radius=r;void main()circle circle1(1);circle*cp;cp=&circle1;couthavevalue=:“;cout circle1.havevalueendl;circle1.circle_prt();coutout by pointer:“;couthavevalueendl;coutout the private data”;coutcircle1.radiusradius;/error初始初始化化禁止访问禁止访问私有数据私有数据返回返回返回返回返返 回回七、面向对象标记两种方法两种方法 UML:统一建模语言 专业的面向对象建模语言,功能强大 较复杂 Coad/Yourdon 类图描述 简单明晰 难以描述成员的访问控制UML对象名对象名数据成员数据成员函数成员函数成员类名类名数据成员数据成员函数成员函数成员Coad/Yourdon消息消息继承包含返返 回回要要点点回回顾顾1.类与对象的概念2.基本类的定义与使用1.类定义的格式:class name 2.访问控制3.对象创建与撤销1.类内、类外的理解2.数据成员与函数成员的区别3.public 与private:公共接口与隐藏1.构造、析构函数:公有、无返回值2.拷贝构造函数3.组合类1.定义:类中内嵌对象?问:内嵌类的定义是组合类吗2.组合类构造与析构:调用顺序4.类模板1.设计思想:数据处理的通用性,参数化程序设计2.适用范围:普通数据类型、自定义数据类型、类3.注意事项:成员函数是模板函数、代码要通用返返 回回Class Apublic:int a,b,c;private:int x,y,z;返返 回回A a1,a2,a3;Class Apublic:int a,b,c;private:int x,y,z;公共接口公共接口内部数据,隐私内部数据,隐私返返 回回1.构造函数与析构函数的功能?2.默认构造函数:系统可以产生缺省的构造函数与析构函数3.构造函数可以重载,析构函数可以重载吗?返返 回回1.为什么需要拷贝构造函数?为什么需要拷贝构造函数?格式:格式:类名(类名&对象名)2.那些情形调用拷贝构造函数?那些情形调用拷贝构造函数?1.用同类对象初始化另一个对象2.用于对象参数传递3.函数的返回值是对象?如何理解返返 回回class outerpublic:int a;class inner public:int b;inner()coutrun the inner constructorendl;void show()coutthe data of inner is:bendl;inn;outer()coutrun the outer constructorendl;void show()coutthe data of outer is:aendl;void main()outer o1;o1.a=123;o1.inn.b=23;o1.show();o1.inn.show();返返 回回可以这样定义吗?可以这样定义吗?不提倡不提倡若调用缺省构造函数(即无形参的),则内嵌对象的初始化也将调用相应的缺省构造函数。内嵌对象的构造函数声明顺序声明顺序调用本类的构造函数调用本类的析构函数内嵌对象的析构函数构造:构造:析构:析构:?如何理解?如何理解返返 回回设计思想皆设计思想皆为参数化程为参数化程序设计序设计实现数据实现数据处理通用性处理通用性1、函数模板、函数模板:2、类模板:、类模板:问题:在函数模板中与类模板中能处理以类问题:在函数模板中与类模板中能处理以类为类型参数的通用数据吗?为类型参数的通用数据吗?返返 回回template 函数定义(内部使用函数定义(内部使用T)template 类定义类定义 请看下例:请看下例:class class_studentpublic:int id;float gpa;class_student(int a,float b)id=a;gpa=b;class_student();struct struct_student int id;float gpa;template class store private:T item;int havevalue;int flag;public:store(void);T getelem(void);void putelem(T x);templatevoid store:putelem(T x)havevalue+;item=x;这样做可以这样做可以吗?吗?Storecla_s1;storestr_s1;回答:回答:1.请大家一起请大家一起 看完例子寻找结论看完例子寻找结论2.无论是函数模板还是类模板,其基本目标是一致的,皆为能处理多种类型的数据,只不过一种实现的载体是函数,一种实现的载体是类实践去探讨,实践去探讨,领会!领会!单元自测(45分钟)见见WORD 文档文档面向对象的现实渊源现实中的简化模现实中的简化模型型冯冯.诺依曼诺依曼计算机计算机遗传算遗传算法法神经网络神经网络谁来开这加飞谁来开这加飞机?机?跳跳 回回