C程序设计课件:第17章 多重继承_第1页
C程序设计课件:第17章 多重继承_第2页
C程序设计课件:第17章 多重继承_第3页
C程序设计课件:第17章 多重继承_第4页
C程序设计课件:第17章 多重继承_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

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

文档简介

1、第17章 多重继承本章主要内容 17.1 多继承如何工作 17.2 继承的模糊性 17.3 虚拟继承 17.4 多继承的构造顺序 17.5 继承的访问控制 17.6 保护继承与私有继承 作业217.1多继承如何工作 多重继承即多继承:由多个基类派生而成新的类 例如,两用沙发,它是一个沙发,也是一张床,两用沙发应允许同时继承沙发和床的特性,即SleeperSofa类继承Bed和Sofa两个类。3Sleep()SetWeight()BedWeightWatchTv()SetWeight()SofaWeightFoldOut()SleeperSofa床和沙发的分解4/* ch17_1.cpp *#i

2、ncludeclass Bed public: Bed() :weight(0) void Sleep() coutSleeping.n; void SetWeight(int i) weight =i; protected: int weight;class Sofa public: Sofa() :weight(0) void WatchTV() cout Watching TV.n; void SetWeight(int i) weight =i; protected: int weight;5class SleeperSofa :public Bed, public Sofa publ

3、ic: SleeperSofa() void FoldOut() /折叠与打开 coutFold out the sofa.n; ;int main() SleeperSofa ss; ss.WatchTV(); ss.FoldOut(); ss.Sleep();运行结果:Watching TV.Fold out the sofa.Sleeping617.2 继承的模糊性 模糊性:二义性二义性:对某个成员访问不能唯一确定二义性产生的原因:不同类的成员可以同名规定:在多继承、多层次的继承结构中,总是逐层往上、访问最靠近自己的那个同名成员。但是,如果在同一层的两个类中具有同名成员,则产生二义性。

4、7int main() sleepersofa ss; ss.SetWeight(20); /error /是Bed的SetWeight还是sofa的SetWeight?这导致了名称冲突,在编译时将予以拒绝。程序必须在重量面前说明基类int main() sleepersofa ss; ss.Sofa:SetWeight(20); /说明是沙发重量20斤17.2 继承的模糊性817.2 继承的模糊性 二义性解决办法: 在成员名前用类名进行限定(类名:成员名),可以解决同一层的两个类中具有同名成员而产生的二义性。 虚基类(即虚拟继承),可以解决上述访问同一个基类的成员,但存在多条路径的问题。91

5、7.3 虚拟继承 从意义上来看,一个SleepSofa没有沙发和床两种重量,如此的继承不是真实的现实世界描述。进一步分析可得,床和沙发都是家具的一种,凡家具都有重量,所以通过分解来考察其关系。10GetWeight()SetWeight()FurnitureWeightGetWeight()SetWeight()FurnitureWeightSleep()BedWatchTv()SofaFoldOut()SleeperSofa沙发床的分解11/* ch17_2.cpp *#includeclass Furniture public: Furniture() void SetWeight(int

6、 i) weight =i; int GetWeight() return weight; protected: int weight;class Bed :public Furniture public: Bed() void Sleep() cout Sleeping.n; ;12class Sofa :public Furniture public: Sofa() void WatchTV() cout Watching TV.n; ;class SleeperSofa :public Bed, public Sofa public: SleeperSofa() :Sofa(), Bed

7、() void FoldOut() cout Fold out the sofa.n; ;int main() SleeperSofa ss; ss.SetWeight(20); /编译出错!模糊的SetWeight成员 Furniture* pF; pF=(Furniture*)&ss; /编译出错!模糊的Furniture* cout GetWeight() endl;13GetWeight()SetWeight()FurnitureWeightGetWeight()SetWeight()FurnitureWeightSleep()BedWatchTv()SofaFoldOut()Slee

8、perSofaSleeperSofa的实际继承关系14Furniture weightBed继承部分 Furniture weightSofa继承部分SleepSofa继承部分床部分沙发部分SleepSofa完整对象完整的SleeperSofa对象内存布局1517.3 虚拟继承 虚拟继承的概念: 在多条继承路径上存在一个公共的基类,在这些路径的汇合处(某个派生类)就产生这个公共基类的多个“副本”。如果只希望存在一个副本,可以把此公共基类声明为虚基类(虚拟继承)。 虚拟继承的方法: 虚基类是对派生类而言,所以,虚基类本身的定义不变,在定义派生类时声明该基类为虚基类即可(冠以关键字:virtual

9、)。 16/* ch17_3.cpp *#includeclass Furniture public: Furniture() void SetWeight(int i) weight =i; int GetWeight() return weight; protected: int weight;class Bed :virtual public Furniture public: Bed() void Sleep() cout Sleeping.n; ;17class Sofa :virtual public Furniture public: Sofa() void WatchTV()

10、cout Watching TV.n; ;class SleeperSofa :public Bed, public Sofa public: SleeperSofa() :Sofa(), Bed() void FoldOut() cout Fold out the sofa.n; ;int main() SleeperSofa ss; ss.SetWeight(20); cout ss.GetWeight() endl;运行结果: 20 18 Furniture weightBed继承部分Sofa继承部分SleeperSofa部分虚拟继承的完整SleeperSofa对象虚拟继承的Sleepe

11、rSofa内存布局虚拟继承的虚拟和虚拟函数的虚拟没有任何关系!1917.4 多继承的构造顺序派生类的构造函数调用次序(调用原则):1. 先基类,再成员,后自己。2. 在同一层上如有多个基类,则先虚基类,后非虚基类。3. 在同一层上如有多个虚基类,则按派生时定义的先后次序执行;在同一层上如有多个非虚基类,则按派生时定义的先后次序执行。 4. 对于一个派生类的某个虚基类的构造函数一旦被执行过,就不再被多次执行。5. 虚基类的派生类的构造函数的定义无特殊规定。2017.4 多继承的构造顺序6. 如果“最后派生类”的构造函数的初始化列表中不调用虚基类的构造函数,则该派生类的虚基类的构造函数必须是无参的

12、,或全部是缺省值的构造函数7. 如果“最后派生类”的构造函数的初始化列表中不调用虚基类的构造函数,则虚基类的初始值采用其构造函数的缺省值;如果“最后派生类”的构造函数的初始化列表中调用了虚基类的构造函数,并且带入初始值,则虚基类的初始值采用带入的值。21/* ch17_4.cpp *#includeclass OBJ1 public: OBJ1() cout OBJ1n; ;class OBJ2 public: OBJ2() cout OBJ2n; ;class Base1 public: Base1() cout Base1n; ;class Base2 public: Base2() co

13、ut Base2n; ;22class Base3 public: Base3() cout Base3n; ;class Base4 public: Base4() cout Base4n; ;class Derived :public Base1, virtual public Base2, public Base3, virtual public Base4 protected: OBJ1 obj1; OBJ2 obj2; public: Derived() :Base4(), Base3(), Base2(), Base1(), obj2(), obj1() cout Derived

14、ok.n; ;23int main() Derived aa; cout This is ok.n;运行结果: Base2 Base4 Base1 Base3 OBJ1 OBJ2 Derived ok. This is ok. 在语言中实现多重继承并不容易,这主要是编译程序问题,还有模糊性问题。建议你如果可能,尽量避免用多重继承。单个继承提供了足够的功能,不一定非用多重继承不可。24#includeclass Base1 /虚基类 private: int a,b; public: Base1(int aa=0,int bb=0) /构造函数:是带缺省值的,或者是无参数的 a=aa; b=bb

15、; coutBase1 class!endl; void show()coutBase1: a=a b=bendl; ;class Base2 public: Base2() coutBase2 class!endl; void show2() coutBase2: endl; ;25class Level1: public Base2,virtual public Base1 public: Level1(int a,int b):Base1(a,b) coutLevel1 class!endl; ;class Level2:public Base2,virtual public Base1

16、 /虚基类 public: Level2(int a,int b):Base1(a,b) coutLevel2 class!endl; ;class Lastlevel: public Level1,virtual public Level2 public: Lastlevel(int a,int b):Level1(a,b), Level2(a,b) /Lastlevel(int a,int b):Level1(a,b), Level2(a,b), Base1(a,b) coutLastlevel class!endl; ;26int main() Lastlevel obj(7,9); o

17、bj.show(); /直接调用间接基类base的公有成员函数show(),无二义性 /obj.show2(); error /访问间接基类base2的公有成员函数show2(),存在二义性 执行结果:Base1 class!Base2 class!Level2 class!Base2 class!Level1 class!Lastlevel class!Base1: a=0 b=0 /Base1: a=7 b=9 2717.5 继承类别及其访问控制继承方式基类成员特性基类中的成员在派生类中的特性公有继承(public)publicpublicprotectedprotectedprivate

18、不可访问私有继承(private)publicprivateprotectedprivateprivate不可访问保护继承(protected)publicprotectedprotectedprotectedprivate不可访问2817.5 继承类别及其访问控制公有成员:一个类的公有成员允许本类的成员函数、本类的对象、公有派生类的成员函数、公有派生类的对象访问。私有成员:一个类的私有成员只允许本类的成员函数访问。保护成员:具有私有成员和公有成员的特性,对其派生类而言是公有成员,对其对象而言是私有成员。2917.5 继承类别及其访问控制公有继承:基类的公有段成员被继承为公有的,基类的保护段成

19、员被继承为保护的。派生时用“public”作访问控制。私有继承:基类的公有段成员被继承为私有的,基类的保护段成员被继承为私有的,派生时用“private”作访问控制。保护继承:基类的公有段成员被继承为保护的,基类的保护段成员被继承为保护的,派生时用“protected”作访问控制。30class Base public: int m1; protected: int m2; private: int m3;class PrivateClass:private Base /私有继承 public: void test() m1=1; /ok:将m1据为private m2=2; / ok:将m2

20、据为private m3=3; /不可访问 ;31class DerivedFromPri:public PrivateClass public: void test() m1=1; /不可访问基类的私有成员 m2=2; /不可访问 m3=3; /不可访问 ;class ProtectedClass:protected Base /保护继承 public: void test() m1=1; /m1据为protected m2=2; /m2据为protected m3=3; /不可访问 ;32class DerivedFromPro:public ProtectedClass public:

21、void test() m1=1; /m1为protected m2=2; /m2仍为protected m3=3; /不可访问 ;class PublicClass:public Base /公共继承 public: void test() m1=1; /m1为public m2=2; /m2为protected m3=3; /不可访问 ; 33class DerivedFromPub:public PublicClass public: void test() m1=1; /m1仍保持为public m2=2; /m2仍保持为protected m3=3; /不可访问 ;int main(

22、) PrivatedClass priObj1; priObj1.m1=1; /error priObj1.m2=2; /error priObj1.m3=3; /error ProtectedClass proObj2; priObj2.m1=1; /error priObj2.m2=2; /error priObj2.m3=3; /error PublicClass pubObj3; priObj3.m1=1; /ok priObj3.m2=2; /error priObj3.m3=3 /error3417.5 继承类别及其访问控制 私有继承时,基类中不管是公有还是保护的成员,在子类中一律

23、变成私有成员。保护继承时,基类中公共和保护的成员在子类中变成保护的。公共继承时,基类中为公共、保护的成员在子类中仍保持为公共、保护的。在继承关系中,基类的private成员不但对应用程序隐藏,对派生类也隐藏。而基类的保护成员则只对应用程序隐藏,而对派生类则毫不隐瞒。 3517.6 保护继承与私有继承一个私有的或保护的派生类不是子类,因为非公有的派生类不能做基类能做的所有的事情,但有与基类相似的行为。例如,下面的代码定义了一个私有继承基类的类。 #include class Animal public: Animal() void eat() couteatn ; ;36class Giraffe:private Animal public: Giraffe() void StrechNeck(double) coutstrechn;class Cat:public Animal public: Cat() void Meaw(

温馨提示

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

评论

0/150

提交评论