第十七章多重继承优秀课件.ppt
《第十七章多重继承优秀课件.ppt》由会员分享,可在线阅读,更多相关《第十七章多重继承优秀课件.ppt(83页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第十七章多重继承第1页,本讲稿共83页2本章主要内容多继承如何工作多继承的构造顺序继承的模糊性(二义性问题)虚基类保护继承与私有继承保护继承与私有继承第2页,本讲稿共83页3在现实世界中存在一个类是由多个类派生的情况。两用沙发,它是一个沙发,也是一个床。两用沙发应允许同时继承沙发和床的特征。第3页,本讲稿共83页4多继承时派生类的定义class 派生类名:继承方式1 基类名1,继承方式2 基类名2,.成员定义;注意注意:每一个:每一个“继承方式继承方式”,只用于限,只用于限制对紧随其后之基类的继承。制对紧随其后之基类的继承。第4页,本讲稿共83页5,所讨论的类层次中,每个类只继承一个父辈,在现
2、实世界中事情通常是这样的。但是一些类却代表两个类的合成。例如,两用沙发,它是一个沙发,也是一张床,两用沙发应允许同时继承沙发和床的特征,即SleeperSofa继承Bed和Sofa两个类,如图所示。其程序代码如下:两用沙发的类层次 第5页,本讲稿共83页6class Bedpublic:Bed():weight(0)void Sleep()cout Sleeping.n;void SetWeight(int i)weight=i;protected:int weight;class Sofapublic:Sofa():weight(0)void WatchTV()cout Watching T
3、V.n;void SetWeight(int i)weight=i;protected:int weight;第6页,本讲稿共83页7class SleeperSofa:public Bed,public Sofapublic:SleeperSofa()void FoldOut()cout Fold out the sofa.n;void main()SleeperSofa ss;ss.WatchTV();ss.FoldOut();ss.Sleep();cin.get();第7页,本讲稿共83页8运行结果为:Watching TV Fold out the sofa Sleeping两用沙发继
4、承两个基类的所有成员,这样ssSleep()和ssWmchTV()的调用是合法的。也就可以把SleeperSofa)fa当作一个Bed或一个Sofa用。另外,SleeperSoa类还有它自己的成员FoldOut()。第8页,本讲稿共83页9多继承举例class A public:void setA(int);void showA();private:int a;class B public:void setB(int);void showB();private:int b;class C:public A,private B public:void setC(int,int,int);void
5、 showC();private:int c;第9页,本讲稿共83页void A:setA(int x)a=x;void B:setB(int x)b=x;void C:setC(int x,int y,int z)SetA(x);SetB(y);c=z;/其它函数实现略int main()C obj;obj.setA(5);obj.showA();obj.setC(6,7,9);obj.showC();obj.setB(6);obj.showB();return 0;/error/error第10页,本讲稿共83页11本章主要内容本章主要内容多继承如何工作多继承如何工作继承的模糊性(二义性问
6、题)继承的模糊性(二义性问题)多继承的构造顺序多继承的构造顺序虚基类虚基类第11页,本讲稿共83页12Sofa和Bed都有一个成员weight,这是合理的,因为两者都是实体,都有一个重量。问题是SleeperSofa继承哪个重量?既然两者都继承,由于两者有相同的名字weight,使得对weight的引用变得模糊不清。第12页,本讲稿共83页13二义性问题在多继承时,基类之间出现同名成员时,将出现访问时的二义性(不确定性)。例如,按照下面引用:例如,按照下面引用:void main()SleeperSofa ss;ss.SetWeight(20);/Bed的的SetWeight还是还是Sofa的
7、的SetWeight?第13页,本讲稿共83页14这样导致了名称冲突(name collision),在编译时将予以拒绝。程序必须在重量前面说明基类:void main()SleeperSofa ss;ss.Sofa:SetWeight(20);/说明是沙发重量20斤 在编写应用程序时,程序员还得额外知道类的层次信息,加大了复杂度。这些在单继承中是不会出现的。第14页,本讲稿共83页15二义性问题举例class A public:void f();class B public:void f();void g();class C:public A,public B public:void g()
8、;void h();main()C c;c.f();c.g();/error第15页,本讲稿共83页16二义性的解决方法解决方法一:用类名来限定c1.A:f()或 c1.B:f()解决方法二:同名覆盖在C 中定义一个同名成员函数f(),f()再根据需要调用 A:f()或 B:f()第16页,本讲稿共83页17二义性问题的说明二义性检查是在访问控制或类型检查之前进行的。因此当不同基类成员中具有相同名字时就会出现二义性,即只有一个名字是可以被派生类访问或只有一个名字的类型与要求相符。第17页,本讲稿共83页18本章主要内容本章主要内容多继承如何工作多继承如何工作继承的模糊性(二义性问题)继承的模糊
9、性(二义性问题)虚基类虚基类多继承的构造顺序多继承的构造顺序第18页,本讲稿共83页19为什么要引入虚基类?在C+中,一个类不能多次说明为派生类的直接基类,但一个类可以不止一次的成为某个类的间接基类。第19页,本讲稿共83页20从意义上来看,一个SleeperSofa没有沙发和床两种重量,如此的继承不是真实的现实世界描述。进一步分析可得,床和沙发都是家具的一种,凡家具都有重量,所以通过分解来考察其关系,如图 第20页,本讲稿共83页21class Furniturepublic:Furniture()void SetWeight(int i)weight=i;int GetWeight()re
10、turn weight;protected:int weight;class Bed:public Furniturepublic:Bed()void Sleep()cout Sleeping.n;class Sofa:public Furniturepublic:Sofa()void WatchTV()cout Watching TV.n;第21页,本讲稿共83页22class SleeperSofa:public Bed,public Sofapublic:SleeperSofa():Sofa(),Bed()void FoldOut()cout Fold out the sofa.n;vo
11、id main()SleeperSofa ss;ss.SetWeight(20);/编译出错!模糊的SetWeight成员 Furniture*pF;pF=(Furniture*)&ss;/编译出错!模糊的Furniture*cout GetWeight()endl;第22页,本讲稿共83页23因为SlleperSofa不是直接继承Furniture,而是Bed和Sofa各自继承Furniture,所以完整的SleeperSofa对象内存布局如图 所示 完整SleeperSofa对象内存布局 第23页,本讲稿共83页24这里一个Sleepersofa包括一个完整的Bed,随后还有一个完整的So
12、fa,后面还有一个 Sleepersofa特有的东西。SleeperSofa中的每一个子对象都有它自己的Furniture部分。因为每个子对象继承Furniture,所以一个SleeperSofa包含两个Furniture对象,编译源文件时,不知道SetWeight()属于哪一个Furniture成员,指向Furniture的指针也不知道究竟指哪一个Furniture。这就是为什么源文件编译通不过的原因。SleeperSofa只需一个Fumiture,所以我们希望它只含一个Furniture拷贝,同时又要共享Bed和Sofa的成员函数与数据成员,C+实现这种继承结构的方法称为虚拟继承虚拟继承(
13、virtual inheritance)。第24页,本讲稿共83页25虚基类的概念当在多条继承路径上有一个公共的基类,在这些路径中的某几条的交汇处,这个公共的基类就会产生多个副本。在大多数的应用场合,需要派生类对象中所含基类的副本只有一个,而不是多个。C+中的虚基类机制可以实现这种要求。第25页,本讲稿共83页26定义用 virtual 修饰说明基类 例例:class x1:virtual public x /class x2:virtual public x /注意:在第一级继承时就要将共同基类设计为在第一级继承时就要将共同基类设计为虚基类。虚基类。第26页,本讲稿共83页27虚基类举例cl
14、ass B public:int b;class B1:virtual public B private:int b1;class B2:virtual public B private:int b2;class C:public B1,public B2 private:float d;下面的访问是正确的:下面的访问是正确的:C obj;obj.b;第27页,本讲稿共83页28虚基类的派生类对象存储结构示意图:BB1B2Cb1b2dB1类子对象B2类子对象C类对象bB类子对象第28页,本讲稿共83页29下面是虚拟继承的代码:class Furniturepublic:Furniture()v
15、oid SetWeight(int i)weight=i;int GetWeight()return weight;protected:int weight;class Bed:virtual public Furniturepublic:Bed()void Sleep()cout Sleeping.n;class Sofa:virtual public Furniturepublic:Sofa()void WatchTV()cout Watching TV.n;第29页,本讲稿共83页30class SleeperSofa:public Bed,public Sofapublic:Sleep
16、erSofa():Sofa(),Bed()void FoldOut()cout Fold out the sofa.n;void main()SleeperSofa ss;ss.SetWeight(20);cout ss.GetWeight()虚拟继承的虚拟和虚拟函数的虚拟没有任何关系。虚拟继承的虚拟和虚拟函数的虚拟没有任何关系。第31页,本讲稿共83页32虚基类及其派生类构造函数在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该虚基类的默认构造函数。在建立对象时,只有最新派生类的构造函数调用虚基类的构造函
17、数,该派生类的其它基类对虚基类构造函数的调用被忽略。虚基类的构造函数先于非虚基类的构造函数执行。第32页,本讲稿共83页33应用举例人员管理系统:有三类人员:经理、技术人员、推销人员,还有销售经理。月薪:经理:8000元/月;技术人员:100元/小时;推销人员:4%提成;销售经理:5000元月+5%提成。输出每个人员的月工资信息。第33页,本讲稿共83页34应用举例类设计基类:employee派生类:technician、manager和salesman多继承派生类:salesmanager第34页,本讲稿共83页35class employee protected:char*name;/姓名
18、姓名 int individualEmpNo;/个人编号个人编号 float accumPay;/月薪总额月薪总额 static int employeeNo;/本公司职员本公司职员编号目前最大值编号目前最大值 public:employee();/构造函数构造函数 employee();/析构函数析构函数 virtual void pay()=0;/计算月薪函数计算月薪函数 virtual void displayStatus()=0;/显示人员信息显示人员信息 ;第35页,本讲稿共83页36 class technician:public employee /技术人员类 private:f
19、loat hourlyRate;/每小时酬金每小时酬金 int workHours;/当月工作时数当月工作时数 public:technician();/构造函数构造函数 void pay();/计算月薪函数计算月薪函数 void displayStatus();/显示人员信息显示人员信息;第36页,本讲稿共83页37class salesman:virtual public employee /兼职推销员类 protected:float CommRate;/按销售额提取酬金的百分比按销售额提取酬金的百分比 float sales;/当月销售额当月销售额 public:salesman();
20、/构造函数构造函数 void pay();/计算月薪函数计算月薪函数 void displayStatus();/显示人员信息显示人员信息;第37页,本讲稿共83页38class manager:virtual public employee /经理类 protected:float monthlyPay;/固定月薪数固定月薪数 public:manager();/构造函数构造函数 void pay();/计算月薪函数计算月薪函数 void displayStatus();/显示人员信息显示人员信息 ;第38页,本讲稿共83页39class salesmanager:public manage
21、r,public salesman /销售经理类 public:salesmanager();/构造函数 void pay();/计算月薪函数 void displayStatus();/显示人员信息 ;第39页,本讲稿共83页40employee:employee()char namestr50;/输人雇员姓名时首先临时存放在namestr中coutnamestr;name=new charstrlen(namestr)+1;/动态申请用于存放姓名的内存空间 strcpy(name,namestr);/将临时存放的姓名复制到 name individualEmpNo=employeeNo+;
22、/新输人的员工,其编号为目前最大编号加1accumPay=0.0;/月薪总额初值为0 第40页,本讲稿共83页41employee:employee()delete name;/在析构函数中删除为存放姓名动态分配的内存空间第41页,本讲稿共83页42technician:technician()hourlyRate=100;/每小时酬金100元void technician:pay()cout请输入nameworkHours;accumPay=hourlyRate*workHours;/计算月薪,按小时计酬 cout“兼职技术人员”name“编号“individualEmpNo“本月工资”ac
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第十七 多重 继承 优秀 课件
限制150内