类的继承与多态性课件.ppt

上传人:石*** 文档编号:50892095 上传时间:2022-10-16 格式:PPT 页数:60 大小:3.76MB
返回 下载 相关 举报
类的继承与多态性课件.ppt_第1页
第1页 / 共60页
类的继承与多态性课件.ppt_第2页
第2页 / 共60页
点击查看更多>>
资源描述

《类的继承与多态性课件.ppt》由会员分享,可在线阅读,更多相关《类的继承与多态性课件.ppt(60页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、类的继承与多态性第1页,此课件共60页哦本章内容本章内容类的继承类的继承类的虚函数与多态性类的虚函数与多态性类的静态成员类的静态成员类模板类模板第2页,此课件共60页哦一、继承的概念一、继承的概念继承是软件重用的一种方式。继承是软件重用的一种方式。通过继承建立新类的优越性通过继承建立新类的优越性:通过重用已有代码,提高编程效率,降低软件开发成本;通过重用已有代码,提高编程效率,降低软件开发成本;更有效地保持共有特性的一致性;更有效地保持共有特性的一致性;提高了系统的可维护性;提高了系统的可维护性;是实现多态性的基础。是实现多态性的基础。被继承的类称为被继承的类称为 “父类父类”或或 “基类基类

2、”;继承者被称为继承者被称为 “子类子类”或或 “派生类派生类”;9.1 9.1 类的继承类的继承第3页,此课件共60页哦继承体现了类的继承体现了类的“层次层次”,从层次上来说,从层次上来说,就是位于上层的是基类就是位于上层的是基类,下层的为派生类下层的为派生类;派生类吸收了基类的非派生类吸收了基类的非privateprivate成员,并增成员,并增添新的性能。添新的性能。基类、派生类是相对的。基类、派生类是相对的。第4页,此课件共60页哦基类与派生类示例基类与派生类示例基类基类派生类派生类学生学生本科生本科生,研究生研究生形状形状圆圆,三角形三角形,矩形矩形,球体球体,立方体立方体贷款贷款汽

3、车贷款汽车贷款,住房贷款住房贷款,抵押贷款抵押贷款雇员雇员教职员工教职员工,后勤人员后勤人员账户账户支票账户支票账户,储蓄账户储蓄账户一般地一般地,派生类的对象都派生类的对象都 “是是”其基类的一个对象其基类的一个对象;基类所能基类所能表示的对象集合比派生类所表示的对象集合大表示的对象集合比派生类所表示的对象集合大.eg.eg.矩形类矩形类“是是”四边形类四边形类,反之不成立反之不成立.第5页,此课件共60页哦单继承单继承建筑物建筑物房屋房屋桥梁桥梁纪念塔纪念塔平房平房楼房楼房居民楼居民楼办公楼办公楼单继承单继承:派生类仅由派生类仅由一个一个基类派生而来基类派生而来第6页,此课件共60页哦多继

4、承多继承EmployeeFacultyStaff Administrator Teacher Administrator teacher多重继承多重继承:派生类由多于一个派生类由多于一个的基类派生而成的基类派生而成多级继承多级继承:等于或多于两个等于或多于两个的继承层次的继承层次第7页,此课件共60页哦二、派生类的定义二、派生类的定义定义格式:定义格式:class :派生类新定义成员派生类新定义成员;继承方式包括:继承方式包括:public/protected/private 分别表示派生类分别表示派生类公有公有继承基类,继承基类,派生类派生类保护保护继承基类,继承基类,派生类派生类私有私有继

5、承基类继承基类class A pulbic:A(int aa=0)a=aa;void showA();private:int a;class B:public A public:B(int bb=0)b=bb;private:int b;第8页,此课件共60页哦聚合聚合VS继承继承聚合:聚合:B类对象的成员类对象的成员包括包括A类的一个或多个类的一个或多个对象。对象。继承:继承:B类对象的成员类对象的成员包括包括A类的成员。类的成员。class A pulbic:A(int aa=0)a=aa;void showA();private:int a;class B:public A public

6、:B(int bb=0)b=bb;private:int b;class A pulbic:A(int aa=0)a=aa;void showA();private:int a;class B public:B(int bb=0):aa(0)b=bb;private:int b;A aa;;B-b:int+showA(),+B()B-b:int,-aa:A+B()第9页,此课件共60页哦派派生生类类成成员员的的构构成成后举例基类基类中的中的私有私有成员成员不能不能被派被派生类生类成员成员直接直接引用。引用。派生类对象先存储其基类子对象部分,再存储新增部分。派生类对象先存储其基类子对象部分,再存

7、储新增部分。第10页,此课件共60页哦派生类成员和外部对象访问基类中的私有成员派生类成员和外部对象访问基类中的私有成员派生类专属成员使用基类私有成员的方式:派生类专属成员使用基类私有成员的方式:不能直接使用基类中的私有成员;不能直接使用基类中的私有成员;成员函数方式:派生类成员函数成员函数方式:派生类成员函数需要通过基类提供的需要通过基类提供的公公有或保护有或保护成员函数间接访问成员函数间接访问;外部对象通过基类的外部对象通过基类的公有成公有成员函数员函数使用其私有成员;使用其私有成员;友元方式:友元方式:把派生类定义为基类的友元,则派生类成员把派生类定义为基类的友元,则派生类成员可以可以直接

8、使用直接使用基类成员;而派生类对象则可以基类成员;而派生类对象则可以用友元用友元函数间接使用函数间接使用基类私有成员基类私有成员第11页,此课件共60页哦派生类的三种继承方式派生类的三种继承方式公有继承:公有继承:除基类的私有成员继续为基类的私有成员外,基除基类的私有成员继续为基类的私有成员外,基类的公有成员和保护成员分别成为派生类的公有成员类的公有成员和保护成员分别成为派生类的公有成员和保护成员。和保护成员。私有继承:私有继承:除基类的私有成员继续为基类的私有成员外,基除基类的私有成员继续为基类的私有成员外,基类的公有成员和保护成员将成为派生类的私有成员。类的公有成员和保护成员将成为派生类的

9、私有成员。保护继承:保护继承:除基类的私有成员继续为基类的私有成员外,除基类的私有成员继续为基类的私有成员外,基类的公有成员和保护成员将成为派生类的保护成基类的公有成员和保护成员将成为派生类的保护成员。员。第12页,此课件共60页哦 继承方式继承方式基类成员基类成员publicpublic方式方式派生类内派生类内/类外对象类外对象privateprivate方式方式派生类内派生类内/类外对象类外对象protectedprotected方式方式派生类内派生类内/类外对象类外对象privateprivate不可见不可见不可见不可见不可见不可见protectedprotected可见可见/不可见不可

10、见可见可见/不可见不可见可见可见 /不可见不可见publicpublic可见可见可见可见/不可见不可见 可见可见 /不可见不可见三种继承方式存取权限的关系三种继承方式存取权限的关系类内:指派生类内的成员函数类内:指派生类内的成员函数类外:指类外部定义的派生类对象类外:指类外部定义的派生类对象可见:即可以可见:即可以直接访问直接访问(使用)(使用)不可见:只能不可见:只能间接访问间接访问第13页,此课件共60页哦继承成员的访问属性继承成员的访问属性-举例举例示例 class X private:int a;protected:int b;public:int c;class Y1:public

11、X int d;public:output()return d;Y1的构成的构成-私有:私有:d 保护:保护:b 公有:公有:output(),c不可直接访问:不可直接访问:a(仍属于基类仍属于基类)第14页,此课件共60页哦继承成员的访问属性继承成员的访问属性-举例举例示例class Xprivate:int a;protected:int b;public:int c;class Y2:protected X int d;public:output()return d;Y2的构成的构成-私有:私有:d 保护:保护:b c 公有:公有:output()不可直接访问:不可直接访问:a(仍属于基

12、类仍属于基类)第15页,此课件共60页哦继承成员的访问属性继承成员的访问属性-举例举例示例class Xprivate:int a;protected:int b;public:int c;class Y:private X int d;public:output()return d;Y3的构成的构成-私有:私有:d b c 保护:保护:公有:公有:output()不可直接访问:不可直接访问:a(仍属于基类仍属于基类)第16页,此课件共60页哦(1)public继承方式继承方式在在public继承方式下,派生类内的成员函数中可以访继承方式下,派生类内的成员函数中可以访问基类和派生类中的保护成员

13、,但外部程序中定义的问基类和派生类中的保护成员,但外部程序中定义的派生类对象不可访问基类和派生类中的保护成员。派生类对象不可访问基类和派生类中的保护成员。Eg.例题例题“public继承继承”在在public继承方式下,派生类内的成员函数中可以访问基继承方式下,派生类内的成员函数中可以访问基类和派生类中的保护成员,但外部程序中定义的派生类类和派生类中的保护成员,但外部程序中定义的派生类对象不可访问基类和派生类中的保护成员。对象不可访问基类和派生类中的保护成员。Eg.例题例题“private继承继承”(2)private继承方式继承方式第17页,此课件共60页哦三、派生类的构造函数三、派生类的构

14、造函数继承关系中,基类的两个特殊成员函数继承关系中,基类的两个特殊成员函数-构造函数构造函数和析构函数不能被继承。和析构函数不能被继承。因此,派生类的构造函数不仅要初始化派生类中定因此,派生类的构造函数不仅要初始化派生类中定义的数据成员,而且要初始化派生类中的义的数据成员,而且要初始化派生类中的基类子对基类子对象象(派生类对象中由基类定义的部分称作基类子对象)。派生类对象中由基类定义的部分称作基类子对象)。基类子对象的初始化赋值是通过在派生类构造函数中基类子对象的初始化赋值是通过在派生类构造函数中显式或隐式地显式或隐式地调用基类构造函数实现的。调用基类构造函数实现的。构造函数的执行顺序:先执行

15、基类构造函数,再执行派构造函数的执行顺序:先执行基类构造函数,再执行派生类构造函数。生类构造函数。基类子对象基类子对象派生类派生类专有部分专有部分派生类派生类第20页,此课件共60页哦例例1:1:P267P267例题例题class A int a1;protected:int a2;public:int a3;A()a1=a2=a3=0;A(int x1,int x2,int x3):a1(x1),a2(x2),a3(x3)void out()couta1 a2 a3endl;int Geta1()return a1;返回类返回类第21页,此课件共60页哦class B:public A in

16、t b1;protected:int b2;public:int b3;B()b1=b2=b3=0;B(int x1,int x2,int x3):A(x1,x2,x3)b1=x1+1;b2=x2+2;b3=x3+3;void out()A:out();coutb1 b2 b3endl;int Sum()return Geta1()*b1+a2*b2+a3*b3;隐含调用隐含调用A()显式调用显式调用A(int,int,int)调用类中的调用类中的无参构造函数无参构造函数返回返回main()函数函数/类和类中都有类和类中都有Out(),则用则用:界定其所属,若不加则指的界定其所属,若不加则指的

17、是本类成员是本类成员调用类中的调用类中的带参构造函数带参构造函数第22页,此课件共60页哦void main()void main()B b1,b2(1,2,3);B b1,b2(1,2,3);b1.Out();b1.Out();b2.Out();b2.Out();coutb1.Sum()coutb1.Sum()b2.Sum()endl;b2.Sum()endl;coutsizeof(B)endl;coutsizeof(B)endl;调用类调用类B B中的中的构造函数构造函数初始化对象初始化对象第23页,此课件共60页哦四、派生类的析构函数四、派生类的析构函数撤销派生类对象时,系统先自动调用派

18、生类的析构函数,撤销派生类对象时,系统先自动调用派生类的析构函数,再调用基类的析构函数。再调用基类的析构函数。系统对派生类和基类析构函数的自动调用顺序和其对系统对派生类和基类析构函数的自动调用顺序和其对构造函数的调用顺序正好相反构造函数的调用顺序正好相反。例:类层次中普通析构函数例:类层次中普通析构函数第24页,此课件共60页哦五、基类和派生类的赋值兼容规则五、基类和派生类的赋值兼容规则在满足在满足公有继承公有继承的限制条件下,的限制条件下,C+允许派生类对象到允许派生类对象到基类对象的自动转换,通常称为赋值兼容规则。基类对象的自动转换,通常称为赋值兼容规则。规则规则1:可以用派生类对象:可以

19、用派生类对象为基类对象赋值为基类对象赋值 规则规则2:可以用派生类对象:可以用派生类对象初始化基类的引用对象初始化基类的引用对象 规则规则3:可以用:可以用基类的指针基类的指针指向派生类对象指向派生类对象eg.赋值兼容规则赋值兼容规则eg.类层次中普通析构函数类层次中普通析构函数第25页,此课件共60页哦9.2 多重继承多重继承 多级继承多级继承引例:引例:Windows风格用户界面设计风格用户界面设计 先设计出窗口类、尺寸类、横向先设计出窗口类、尺寸类、横向/纵向滚动条类、按纵向滚动条类、按钮类;用户界面类将上述各类作为基类,通过多重继钮类;用户界面类将上述各类作为基类,通过多重继承产生。承

20、产生。一、多重继承时的派生类一、多重继承时的派生类 1、定义格式:、定义格式:class 派生类名:派生类名:继承方式继承方式1基类名基类名1,继承方式继承方式2基类名基类名2,派生类成员定义派生类成员定义;注:各基类名不能相同注:各基类名不能相同第26页,此课件共60页哦2 2、初始化数据成员、初始化数据成员调用构造函数调用构造函数1 1)调用顺序)调用顺序 构造函数调用顺序:构造函数调用顺序:(1)(1)初始化第一个基类子对象,即调用第一个基类的构造函数;初始化第一个基类子对象,即调用第一个基类的构造函数;初始化第二个基类子对象,即调用第二个基类的构造函数;初始化第二个基类子对象,即调用第

21、二个基类的构造函数;初始化第初始化第n n个基类子对象,即调用第个基类子对象,即调用第n n个基类的构造函数。个基类的构造函数。(2)(2)派生类中若有基类对象作成员,则调用相应基类的构造函数。派生类中若有基类对象作成员,则调用相应基类的构造函数。(3)(3)最后初始化派生类普通成员。最后初始化派生类普通成员。析构函数调用顺序:与构造函数相反。析构函数调用顺序:与构造函数相反。第27页,此课件共60页哦例例:多重继承时的构造函数的调用多重继承时的构造函数的调用P269P269说明:派生类初始化成员的顺序说明:派生类初始化成员的顺序:首先对首先对基类子对象成员基类子对象成员的初始化的初始化,然后

22、对然后对新增对象成员新增对象成员初始化初始化,最后对最后对新增非对象成员新增非对象成员初始化初始化.注注:前两步必须在构造函数的初值表中给出初值项前两步必须在构造函数的初值表中给出初值项 (省略时调用无参构造函数省略时调用无参构造函数););后一步可以通过初值表后一步可以通过初值表,也可以通过函数体进行也可以通过函数体进行.第28页,此课件共60页哦二、多级继承中的派生类二、多级继承中的派生类 class A class A ;class B:public A class B:public A ;class C:public B class C:public B ;B B直接继承类直接继承类A

23、 A,C C直接继承类直接继承类B B,间接继承类,间接继承类A A。eg.P270 eg.P270 多级继承举例多级继承举例多级继承时的初始化顺序多级继承时的初始化顺序:先执行最上层基类的构造函数先执行最上层基类的构造函数,依次依次向下执行各基类的构造函数向下执行各基类的构造函数,最后是当前派生类的构造函数对新增最后是当前派生类的构造函数对新增成员的初始化成员的初始化.第29页,此课件共60页哦 执行执行C C的构造函数前先调用的构造函数前先调用B1B1、B2B2构造函数;执行构造函数;执行B1B1、B2B2构造函数前先分别调用构造函数前先分别调用A A的构造函数。的构造函数。A AB1B1

24、B2B2C CA A为为C C的公共基类的公共基类eg.eg.数据成员二义性数据成员二义性三、混合多继承中的构造函数三、混合多继承中的构造函数class C:public B1,public B2 ;第30页,此课件共60页哦1 1、数据成员二义性、数据成员二义性 假设图中类假设图中类A A有数据成员有数据成员a a,则则C C中有两个中有两个a a成员,成员,a a是哪个是哪个 派生类的成员?产生了二义性。派生类的成员?产生了二义性。解决方法:解决方法:(1)(1)加类名分辨符加类名分辨符B1:B1:或或 B2:B2:(2)(2)定义虚基类定义虚基类 eg1.eg1.数据成员二义性数据成员二

25、义性A(a)A(a)B1(a,b1)B1(a,b1)B2(a,b2)B2(a,b2)C(a,b1,b2,c)C(a,b1,b2,c)四、多继承中二义性问题的解决四、多继承中二义性问题的解决第31页,此课件共60页哦2 2、函数成员二义性、函数成员二义性 B1,B2B1,B2中都含有中都含有print()print()成员函数,成员函数,C C继承了继承了B1,B2B1,B2,则则C C中有两个中有两个print()print()函数。函数。解决方法:加类区分符解决方法:加类区分符:eg2.eg2.函数成员二义性函数成员二义性B1(print()B1(print()B2(print()B2(pr

26、int()C C第32页,此课件共60页哦9.3 9.3 虚基类虚基类消除数据成员二义性的两种方法的区别:消除数据成员二义性的两种方法的区别:(1)(1)”类名类名:”法:消除二义性同时实现程序设计的多态性,但在派生法:消除二义性同时实现程序设计的多态性,但在派生类对象中存在多个公共基类的同名数据成员类对象中存在多个公共基类的同名数据成员 (2)(2)”虚函数虚函数”法:消除二义性,且在派生类对象中只存在一个法:消除二义性,且在派生类对象中只存在一个公共基类的数据成员公共基类的数据成员设计虚基类:设计虚基类:(1)(1)一个基类有多于一个派生类时,一个基类有多于一个派生类时,在这些派生类在这些

27、派生类“继承方式继承方式”前加上前加上 virtual virtual 关键字。关键字。class B1:virtual public Aclass B1:virtual public A class B2:virtual public A class B2:virtual public A 此时将公共基类此时将公共基类A A称为虚基类。称为虚基类。A AB1B1B2B2C C第33页,此课件共60页哦(2)(2)虚基类子对象由最新派生出来的派生类虚基类子对象由最新派生出来的派生类直接初始化直接初始化。B1B1,B2B2对类对类A A子对象初始化,子对象初始化,C C 也要对类也要对类A A子

28、对象初始化。子对象初始化。eg.eg.虚基类虚基类 注意:对非虚基类,不能在中对类注意:对非虚基类,不能在中对类子对象初始化。子对象初始化。A AB1B1B2B2C C第34页,此课件共60页哦9.9.类的虚函数和多态性类的虚函数和多态性对于相同的函数调用,依赖每个对象自己对于相同的函数调用,依赖每个对象自己做出恰当的响应,这是多态性的关键思想。做出恰当的响应,这是多态性的关键思想。多态性(多态性(polymorphismpolymorphism):不同对象在):不同对象在接接收同样的消息收同样的消息时时,所所做出的响应不同做出的响应不同。多态性的实现依赖于动态联编。多态性的实现依赖于动态联编

29、。指调用名称相同指调用名称相同的成员函数的成员函数指不同派生类的成指不同派生类的成员函数员函数第35页,此课件共60页哦一、滞后联编一、滞后联编 联编:指一个标识符名和一个存储地址联系在一起的过程。联编:指一个标识符名和一个存储地址联系在一起的过程。1 1、静态联编(早期联编)、静态联编(早期联编)指:联编工作出现在指:联编工作出现在编译编译连接阶段,因为这种联编过连接阶段,因为这种联编过程在程序开始运行之前完成,所以又称早期联编。程在程序开始运行之前完成,所以又称早期联编。在编译时就解决了程序中的操作调用与执行该操作代码间在编译时就解决了程序中的操作调用与执行该操作代码间的关系,确定这种关系

30、又被称为束定,因此,静态联编又称为静态的关系,确定这种关系又被称为束定,因此,静态联编又称为静态束定。束定。2 2、动态联编(滞后联编)、动态联编(滞后联编)指:在程序指:在程序执行时执行时进行的联编,称动态联编,或称动态束进行的联编,称动态联编,或称动态束定,又叫滞后联编。定,又叫滞后联编。动态联编时在不同阶段被束定的类的对象将是不同的动态联编时在不同阶段被束定的类的对象将是不同的。动态联编的实现:动态联编的实现:C+C+中,在中,在虚函数虚函数的支持下实现。的支持下实现。第36页,此课件共60页哦二、虚函数的定义二、虚函数的定义、定义:、定义:virtual virtual 成员函数原型;

31、成员函数原型;、注意:、注意:(1)(1)只有在类的继承关系中才存在虚函数只有在类的继承关系中才存在虚函数。在基类中声明某成员。在基类中声明某成员函数为虚函数,则派生类中(名字、参数个数、参数类型和返回函数为虚函数,则派生类中(名字、参数个数、参数类型和返回值类型都)相同的成员函数都视作虚函数。值类型都)相同的成员函数都视作虚函数。(2)(2)使用虚函数须使用虚函数须利用赋值兼容规则利用赋值兼容规则,要求,要求publicpublic继承方式。继承方式。(3)(3)多态性使我们编写的程序在处理同一个类层次结构下类的对象多态性使我们编写的程序在处理同一个类层次结构下类的对象时好像它们是基类的所有

32、对象一样。时好像它们是基类的所有对象一样。第37页,此课件共60页哦三、虚函数的使用三、虚函数的使用 多态性是利用多态性是利用基类的指针句柄和基类的引用句柄基类的指针句柄和基类的引用句柄,而不是利用名字句柄。而不是利用名字句柄。实现多态的步骤:实现多态的步骤:(1)(1)定义基类指针定义基类指针 (2)(2)用该指针指向基类或派生类对象用该指针指向基类或派生类对象(3)(3)当程序发送当程序发送虚函数消息虚函数消息时:若指针指向基类对象,时:若指针指向基类对象,系统调用基类成员函数,若指针指向派生类对象,系统调用基类成员函数,若指针指向派生类对象,系统调用派生类成员函数。系统调用派生类成员函数

33、。(4)(4)若没有步骤若没有步骤(2)(2)中赋值,系统按早期联编方式调用中赋值,系统按早期联编方式调用基类成员函数。基类成员函数。第38页,此课件共60页哦class X1 int x;public:X1(int xx=0)x=xx;virtual void Output()cout“x=“xendl;class Y1:public X1 int y;public:Y1(int xx=0,int yy=0):X1(xx)y=yy;virtual void Output()X1:Output();cout“y=“yendl;可以去掉这里的可以去掉这里的virtual例例:虚函数虚函数第39页

34、,此课件共60页哦class Z1:public X1 int z;public:Z1(int xx=0,int zz=0):X1(xx)z=zz;virtual void Output()X1:Output();cout“z=“zendl;void main()X1 a(5);Y1 b(6,7);Z1 c(8,9);X1*p3=&a,&b,&c;for(int i=0;iOutput();coutact1();结果如何?结果如何?3、如果将、如果将A中中act1()前的前的virtual 去掉,结果如何?去掉,结果如何?例:例:#include class A public:virtual

35、void act1();void act2()act1();void A:act1()cout“A:act1()called.”endl;class B:public A public:void act1();void B:act1()cout“B:act1()called.”endl;B:act1()called.B:act1()called.A:act1()called.可以由成可以由成员函数调员函数调用虚函数用虚函数第42页,此课件共60页哦四、构造函数中调用虚函数#include class A public:A()virtual void f()cout“A:f()called.n”

36、;class B:public A public:B()f();void g()f();class C:public B public:C()virtual void f()cout“C:f()called.n”;void main()C c;c.g();结果:结果:A:f()called.C:f()called.结论:构造函数中调用虚函数时,釆用静态联编,即构造函数结论:构造函数中调用虚函数时,釆用静态联编,即构造函数调用的虚函数是自己类中实现的虚函数,如果自己类中没有实调用的虚函数是自己类中实现的虚函数,如果自己类中没有实现这个虚函数,则调用基类中的虚函数。现这个虚函数,则调用基类中的虚函

37、数。第43页,此课件共60页哦例:定义普通析构函数例:定义普通析构函数#include class AA int i;public:AA(int n):i(n)AA()cout“AA“endl;class BB:public AA char*p;public:BB(int n,char*s):AA(n)p=new charstrlen(s)+1;strcpy(p,s);BB()delete p;cout“BB”endl;void main()AA*p=new BB(5,”abcd”);delete p;结果结果:AA普通析构函数在使用普通析构函数在使用delete删除一删除一个对象时,是静态联

38、编,关联的只是个对象时,是静态联编,关联的只是基类的析构函数。基类的析构函数。五、虚析构函数五、虚析构函数第44页,此课件共60页哦#include class AA int i;public:AA(int n):i(n)virtual AA()cout“AA“endl;class BB:public AA char*p;public:BB(int n,char*s):AA(n)p=new charstrlen(s)+1;strcpy(p,s);BB()delete p;cout“BB”endl;void main()AA*p=new BB(5,”abcd”);delete p;结果结果:BB

39、AA虚析构函数的目的在于使用虚析构函数的目的在于使用delete删除一个对象时,是动态联编,删除一个对象时,是动态联编,关联的是子类的析构函数。关联的是子类的析构函数。例:定义虚析构函数例:定义虚析构函数第45页,此课件共60页哦六、纯虚函数与抽象类六、纯虚函数与抽象类软件使用者:某软件只要用到一些具体事物的类(如:软件使用者:某软件只要用到一些具体事物的类(如:Sphere,Cylinder,Cone类)类)软件设计者:增加一个更抽象的基类效果更好(代码重用)软件设计者:增加一个更抽象的基类效果更好(代码重用)(如:(如:Circle类)类)-某些成员函数在基类中的实现变得没意义(如:某些成

40、员函数在基类中的实现变得没意义(如:Area(),Volume()函数),但其声明仍有意义。函数),但其声明仍有意义。问题:能否将这样的成员函数在基类中只作声明,而其实现留给派问题:能否将这样的成员函数在基类中只作声明,而其实现留给派生类呢?生类呢?用纯虚函数将基类改造为抽象类用纯虚函数将基类改造为抽象类第46页,此课件共60页哦1、纯虚函数、纯虚函数定义:定义:virtual 返回类型返回类型 函数名(参数表)函数名(参数表)=0纯虚函数在基类中声明,具体实现在派生类中。纯虚函数在基类中声明,具体实现在派生类中。2、抽象类、抽象类包含纯虚函数的类称为抽象类。包含纯虚函数的类称为抽象类。抽象类

41、为其所有子类提供了统一的操作界面。抽象类为其所有子类提供了统一的操作界面。说明:说明:抽象类不能实例化,即不能声明抽象类对象;抽象类不能实例化,即不能声明抽象类对象;抽象类只作为基类被继承,无派生类的抽象类无意义抽象类只作为基类被继承,无派生类的抽象类无意义可定义指向抽象类的指针或引用,它们必然指向派生类对象,可定义指向抽象类的指针或引用,它们必然指向派生类对象,从而实现多态性。从而实现多态性。第47页,此课件共60页哦例:纯虚函数与抽象类例:纯虚函数与抽象类class Shapepublic:virtual double area()=0;class Point double x,y;pub

42、lic:Point(double x0=0.0,double y0=0.0):x(x0),y(y0)double getX()return x;double getY()return y;第48页,此课件共60页哦class RectAngle:public Shape Point ul;/左下角顶点左下角顶点 Point dr;/右上角顶点右上角顶点public:RectAngle(Point p1,Point p2):ul(p1),dr(p2)virtual double area()return(dr.getX()-ul.getX()*(dr.getY()-ul.getY();Point

43、 getUpleft()return ul;Point getDownright()return dr;第49页,此课件共60页哦class Circle:public Shape Point cen;/圆心圆心 double rad;/半径半径public:Circle(Point c,double r):cen(c),rad(r)virtual double area()return 3.1415926*rad*rad;Point getCenter()return cen;double getRadius()return rad;void showArea(Shape&s)couts.a

44、rea();void main()RectAngle r(Point(2.0,2.0),Point(8.0,8.0);showArea(r);coutendl;Circle c(Point(8,8),4);showArea(c);通过调用通过调用showArea()这同一动作,这同一动作,计算出不同形状的面积,即同一消息,计算出不同形状的面积,即同一消息,不同响应不同响应-多态性。多态性。第50页,此课件共60页哦9.5类的静态成员类的静态成员在类成员声明前加上在类成员声明前加上static修饰即把该成员声明为该类的静态成员;修饰即把该成员声明为该类的静态成员;static数据成员数据成员静态

45、数据成员必须在定义第一个对象之前作为静态变量加以定静态数据成员必须在定义第一个对象之前作为静态变量加以定义并初始化;义并初始化;静态函数成员没有静态函数成员没有this指针,只能直接访问类中的静态成员(如要指针,只能直接访问类中的静态成员(如要访问类中非静态成员,必须借助对象名或指向对象的指针)。访问类中非静态成员,必须借助对象名或指向对象的指针)。静态成员不能说明为虚函数。静态成员不能说明为虚函数。一般地,每个对象都存放有其所属类中所有成员的拷贝一般地,每个对象都存放有其所属类中所有成员的拷贝.非非static数据成员数据成员但有时希望程序中的同类对象共享某个成员,解决方法:但有时希望程序中

46、的同类对象共享某个成员,解决方法:(一)将要共享成员说明为全局变量(一)将要共享成员说明为全局变量-破坏封装性破坏封装性(二)(二)将要共享成员说明成类的静态成员将要共享成员说明成类的静态成员-较好较好第53页,此课件共60页哦例例1:类的静态数据成员:类的静态数据成员class XX int a;public:static int b;XX(int aa=0)a=aa;b+;int geta()return a;int XX:b=0;void main()coutXX:bendl;XX x(10),y(20);coutx.geta()“,”x.bendl;couty.geta()“,“y.b

47、endl;x.ay.aXX:b结果:结果:010,220,2静态数据成员可以用静态数据成员可以用来计数,本题中可以来计数,本题中可以用来计该类定义的对用来计该类定义的对象的个数象的个数第54页,此课件共60页哦class MOD100 public:static int add(int x,int y)return(x+y)%100;static int sub(int x,int y)return(x-y)%100;void main()coutMOD100:add(34,89)endl;coutMOD100:sub(34,199)endl;例例2:类的静态函数成员:类的静态函数成员每个每个

48、static成员函数都是类的一项服务,而成员函数都是类的一项服务,而不是类的特定对象的一项服务不是类的特定对象的一项服务。类的类的static成员成员即使在没有任何即使在没有任何类的对象存在时,类的对象存在时,仍然存在。仍然存在。第55页,此课件共60页哦9.6 类模板类模板模板类定义格式:模板类定义格式:template类定义类定义利用类模板定义类对象时,须在利用类模板定义类对象时,须在类名类名后给出后给出,编译系统将自动生成相应的类定义,称为类模板的,编译系统将自动生成相应的类定义,称为类模板的 实例化。实例化。类是对问题空间的抽象,而类模板是对类形式上的抽象。类是对问题空间的抽象,而类模

49、板是对类形式上的抽象。在程序中可以先定义一个模板类,然后通过使用不同实在程序中可以先定义一个模板类,然后通过使用不同实参生成不同类的对象。参生成不同类的对象。回顾:函数模板定义形式回顾:函数模板定义形式-template ()第56页,此课件共60页哦例:类模板例:类模板template class TwoNum Type a;Type b;public:TwoNum():a(0);b(0);TwoNum(Type aa,Type bb):a(aa),b(bb)int Compare();Type Maximum()return(ab)?a:b;Type Minimum()return(ab)

50、?b:a;第57页,此课件共60页哦/在模板外给出模板类中函数的完整定义在模板外给出模板类中函数的完整定义templateint TwoNum:Compare()if(ab)return 1;else if(a=b)return 0;else return-1;模板类中的函数都是模板函数模板类中的函数都是模板函数/模板类的实例化模板类的实例化void main()TwoNumx(4,8);coutx.Compare()x.Maximun()x.Minimum()endl;生成实例:生成实例:class TwoNumint a;int b;第58页,此课件共60页哦模板类模板类类模板的实例可以作

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 大学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁