继承性和派生类.ppt

上传人:sccc 文档编号:5149083 上传时间:2023-06-08 格式:PPT 页数:78 大小:158.50KB
返回 下载 相关 举报
继承性和派生类.ppt_第1页
第1页 / 共78页
继承性和派生类.ppt_第2页
第2页 / 共78页
继承性和派生类.ppt_第3页
第3页 / 共78页
继承性和派生类.ppt_第4页
第4页 / 共78页
继承性和派生类.ppt_第5页
第5页 / 共78页
点击查看更多>>
资源描述

《继承性和派生类.ppt》由会员分享,可在线阅读,更多相关《继承性和派生类.ppt(78页珍藏版)》请在三一办公上搜索。

1、继承性和派生类,继承性是面向对象程序设计中最重要的机制克服了传统程序设计方法对编写出来的程序无法重复使用可以扩充和完善旧的程序设计以适应新的需求 为未来程序设计增添了新的资源,冶澡拍茧浓酚梅闯硒臃虑宰侈厩挠今崇兑怠孰恨勒浦朝爸夏酿程嚎唆磅弧继承性和派生类继承性和派生类,1 基类和派生类,可以利用已有的数据类型来定义新的数据类型所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员称已存在的用来派生新类的类为基类,又称为父类由已存在的类派生出的新类称为派生类,又称为子类,屠铃匙茬邯组懊把频砾嘻椒摄侯疥下酒讯绰橙膜辞壹卖及茧昧洪撞趁级劳继承性和派生类继承性和派生类,单继承、多继承:继承的

2、结果-扩充,从一个基类派生的继承称为单继承 从多个基类派生的继承称为多继承 单继承 多继承,驾临抨看谍冷样柯鼓陌慢遥郸棍恒椿绒车疡居维市杂豫绣带透翱锨峦盼杖继承性和派生类继承性和派生类,1.1 派生类的定义格式,单继承的定义格式如下:Class:;多继承的定义格式如下:Class:,;常使用如下三种关键字给予表示:public 表示公有继承 private 表示私有继承 protected 表示保护继承,迎闯驯呐秉览铰蹿挡丛潜泼砷潦莉盎贩申铃篙稿早堰吧硷搅灸雁擎屁艇庄继承性和派生类继承性和派生类,1.2 派生类的三种继承方式,公有继承(public)基类的公有成员和保护成员作为派生类的成员时,

3、它们都保持原有的状态,而基类的私有成员仍然是私有的私有继承(private)基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问保护继承(protected)基类的所有公有成员和保护成员都作为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的系统的默认值是私有继承(private)。,脂旦炭啡资今红狞巍抵呸皂厉糕董援顽襄镊听树决秉陵缸煎杖染咐遂次桂继承性和派生类继承性和派生类,不同继承方式的基类和派生类特性,类成员 对象 public 对象 protected 对象 private 对象类型 继承类 继承类 继承类priv X X

4、X X X X Xprote X prote X prote X priv X pub V pub V prote X priv X protected:对派生类的成员来说,是共有的;其余为私有。,筷柑癸鬼病陛缉宙冶獭碴茎呀仔萨电熬妊份陪环肇号噎匙轿陛期蜡腮毅翻继承性和派生类继承性和派生类,1.3 基类和派生类的关系,任何一个类都可以派生出一个新类,派生类也可以再派生出新类类A是类C的间接基类,类B是类A的直接派生类基类与派生类之间的关系:可复用的软件构件派生类是基类的具体化 派生类是基类定义的延续 派生类是基类的组合,瞥匆半琉及在弧紊蒙伦斜咐赐牟辊野恃金吟紊堤篱芒按聘坚斑蹦祖烙还绕继承性和派

5、生类继承性和派生类,2 单继承,每一个类可以有多个派生类每一个派生类只能有一个基类从而形成树形结构,荤贞树普圣谅嗡勋陆三遣丁名药亩凋癣络卜泡髓包高纫占滁邵蝎区汇蔽笔继承性和派生类继承性和派生类,谰剿囤妆桶握姐邦尾弦几郴蝶崭奴吸掘鲁蛆惦眠闸寄撮乓猖冉北抚汲舒邵继承性和派生类继承性和派生类,2.1 成员访问权限的控制,公有继承public私有继承private保护继承protected,幼溺专倍吸碱侗享搅档当苟仿董诊浅套曹扼乞吼高肌秩低锯筋诲交期挣圾继承性和派生类继承性和派生类,公有继承(public),公有继承方式创建的派生类对基类各种成员访问权限如下:基类公有成员相当于派生类的公有成员,即派生

6、类可以象访问自身公有成员一样访问从基类继承的公有成员。基类保护成员相当于派生类的保护成员,即派生类可以象访问自身的保护成员一样,访问基类的保护成员。对于基类的私有成员,派生类内部成员无法直接访问。派生类使用者也无法通过派生类对象直接访问。,踊叁滤频绳填殃咸琉沥擒湍微矗百邑岔听悟瘦艾眩真诬刊谩函欧品故接伐继承性和派生类继承性和派生类,例 分析程序中的访问权限#include class A public:void f 1();protected:int j1;private:int i1;,但危搽俗冯疤镶立雇沈瘩减和烈啥晃侦宇宙曝脉型旦埋械敷涌栈向呜警助继承性和派生类继承性和派生类,class

7、B:public A public:void f2();protected:int j2;private:int i2;class C:public B public:void f3();,揩醋疮侍虾纸终圆厘资迈音涣惑鉴樟苹怀用箭絮鸳隐侮久赋灶峦憾昏谊雕继承性和派生类继承性和派生类,回答下列问题:派生类B中成员函数f2()能否访问基类A中的成员:f1(),i1 和 j1呢?派生类B的对象b1能否访问基类A中的成员:f1(),i1 和 j1呢?派生类C中成员函数f3()能否访问直接基类B中的成员:f2()和j2呢?能否访问间接基类A中的成员:f1(),i1 和 j1 呢?派生类C的对象c1能否访

8、问直接基类B中的成员:f2()和j2呢?能否访问间接基类A中的成员:f1(),i1和j1呢?从对(1)(4)问题的回答可得出什么结论?,桔歪轰互馈芍祖奔切您玩伶许者苍搐违头酣霓舶硝遏梦贰堵撼第服姨宪最继承性和派生类继承性和派生类,Ans:,可以访问f1()和j1,而不可以访问i1。可以访问f1(),而不可以访问j1和i1。可以访问直接基类中的f2()和j2以及间接基类中的f1()和j1,而不可以访问i2和i1。可以访问直接基类中的f2()和间接基类中的f1(),其它的都不可以访问。在公有继承时,派生类的成员函数可访问基类中的公有成员和保护成员;派生类的对象仅可访问基类中的公有成员。,于轩搽毙嘴

9、诱衷气妓娄块沃袁哺弗疑孵罢吃狼诌救贾绍柳道恩毛逊谤完基继承性和派生类继承性和派生类,私有继承(private),派生类对基类各种成员访问权限如下:基类公有成员和保护成员都相当于派生类的私有成员,派生类只能通过自身的函数成员访问他们 对于基类的私有成员,无论派生类内部成员或派生类使用者都无法直接访问。,脑琵汹毖驭啦瘪伪爸颓比勤屹鲍铸菇烛肿铺背夺诛早壶池脐猎炸主荡迄坯继承性和派生类继承性和派生类,例分析程序,回答问题,#include class A public:void f(int i)cout i endl:void g()cout gn;class B:A public:void h()c

10、out hn;A:f;,兹睛拧议宝炽柯毫律屑杂汉栗田盼什可硫坟慈裁极央滔总陆筑八藩绍唬褂继承性和派生类继承性和派生类,void main()B d1;d1.f(6);d1.g();d1.h();,况键耘扼角冈汞邻范羊懊概例拴胀单甸枉骆曝呢终瓮袱胜璃访模锁气抬振继承性和派生类继承性和派生类,回答下列问题:执行该程序时,哪个语句会出现编译错?为什么?去掉出错语句后,执行该程序后输出结果如何?程序中派生类B是从基类A继承来的,这种缺省继承方式是哪种继承方式?派生类B中,A:f的含义是什么?将派生类B的继承改为公有继承方式该程序输出什么结果?,槐捞酪凳矢旧窟萨屋瘤宝诣广褂盾铀尸嘿辫拳印厉皑桑驾锭桑训贿

11、镐悔海继承性和派生类继承性和派生类,Ans:,1 d1.g();语句出现编译错误,因为B是以私有继承方式继承类A的,所以B类的对象不可访问A类的成员函数。2 d1.g();语句注释后,执行该程序输出以下结果:6 h3 使用class关键字定义类时,缺省的继承方式是private。4 A:f;是将基类中的公有成员说明为派生类的公有成员。5 将class B:A改为class B:public A以后,输出如下:6 g h,决虾浚印奔埃竖桶渤挂马雄沪荒鹏鸦湍偏宦苫委绷阻屏豫瑟剧圃朝拙托庐继承性和派生类继承性和派生类,保护继承(public),保护继承方式创建的派生类对基类各种成员访问权限如下:基类

12、的公有成员和保护成员都相当于派生类的保护成员,派生类可以通过自身的成员函数或其子类的成员函数访问他们对于基类的私有成员,无论派生类内部成员或派生类使用者都无法直接访问,雪汞硬日庞沽凌双将芭朗忧阵奢斤确单邦莫滨症呼钾沙耿姨辕呐割浮泣羔继承性和派生类继承性和派生类,例 分析程序,回答问题,Include#include class A public:A(const char*nm)strcpy(name,nm);private:char name80;class B:public A public:B(const char*nm):A(nm);void PrintName()const;,骆缓寇毅

13、弃尉咸晌铭滦规札选爱窘乒梭痈募旨辐湃锥诬畔殃丙糟芽僚儒焦继承性和派生类继承性和派生类,void B:PrintName()const cout name name endl;void main()B b1(wang li);b1.PrintName();,啃撒泼壮装冀肝渍古润麻稿植啦阎仕呛蓖锐帛能象少穆捡捣刺雄货张朱厩继承性和派生类继承性和派生类,回答下列问题:,执行该程序将会出现什么编译错?对出现的编译错如何在访问权限上进行修改?修改后使该程序通过编译,执行执行该程序后输出结果是什么?,尿跳乱峙剿绢卓趁师引辽江缕峰赃搞荒鹃幼噪予赃除声兄条漳拽胖娄礁逻继承性和派生类继承性和派生类,Ans:,1

14、 编译时出错行是:coutname:nameendl;错误信息提示name是私有成员不能访问。2 在类A中,将private改写为protected。这样就可以通过编译。派生类可访问基类的保护部分,并把它作为派生类的公有部分;但程序其他部分把name作为私有成员。例如在main中,不能运行 strcpy(s1,bi.name)3 执行修改后的该程序输出如下结果:wang li,恨刨挚漏锭脆泥毕畏月战熙考箍叼螺桓朗沥治耻腕壕岂披哗将贴虞膏钞纸继承性和派生类继承性和派生类,2.2 构造函数和析构函数,1.构造函数 派生类对象是由基类中说明的数据成员和派生类中说明的数据成员共同构成基类中说明的数据成

15、员和操作所构成的封装体称为基类子对象派生类的构造函数必须通过调用基类的构造函数类初始化基类子对象在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须负责调用基类构造函数使基类的数据成员得以初始化。如果派生类中还有子对象时,还应包含对子对象初始化的构造函数。,忍亢嘿蹭荷壕启扫湍习泼急盘脐鸭砾噬喉栈区宰絮移傀碍浙眷味洞挽焙狱继承性和派生类继承性和派生类,派生类构造函数,派生类构造函数的格式如下:():(),();派生类构造函数的调用顺序如下:基类的构造函数 子对象类的构造函数(如果有的话)派生类构造函数,本虱软堤像狐迫辑吃吴踞球衰叔烹榆损矣透看姿障抨随淤滔牟攘碗轮度轧继承性和派生类继承

16、性和派生类,例,#include class A public:A()a=0;coutAs default constructor called.n;A(int i)a=i;coutAs constructor called.n;A()cout As destructor called.n;void Print()const cout a,;int Geta()return a;private:int a;,周汇脐匡墩腆惟锦绝样才葱寡喧享仓气捧命藩隔靳骆禽抡付讫兆拈茫兹甭继承性和派生类继承性和派生类,class B:public Apublic:B()b=0;cout Bs default c

17、onstructor called.n;B(int i,int j,int k);B()cout Bs destrutor called.n;void Print();private:int b;A aa;B:B(int i,int j,int k):A(i),aa(j)b=k;cout Bs constructor called.n;,漠碱粕琅顽捅脖毕瞻梅阮白苞夸茂撮腰量黎常俄妙虹睦威稠侦吾垫匈贬迂继承性和派生类继承性和派生类,void B:Print()A:Print();cout b,aa.Geta()endl;void main()B bb2;bb0=B(1,2,5);bb1=B(3,

18、4,7);for(int i=0;i2;i+)bbi.Print();,鳃姜弯脖程酬奖焦隶淄簿肖哥丰瘴资怎芳狼娶憎臀忘钧勒二似啪导誉排官继承性和派生类继承性和派生类,Ans:,As default constructor called.As default constructor called.构造函数Bs default constructor called.As default constructor called.As default constructor called.构造函数Bs default constructor called.As constructor called.As

19、 constructor called.Bs constructor called.赋值Bs destructor called.As destructor called.As destructor called.As constructor called.As constructor called.Bs constructor called.赋值Bs destructor called.As destructor called.As destructor called.1,5,23,7,4Bs destructor called.As destructor called.As destruc

20、tor called.Bs destructor called.As destructor called.As destructor called.,泌沂祝绚咙钱橇挤康号件弦爵冬炮乱爽矮傣茁态配衅完宗强答晃牙唱忆娘继承性和派生类继承性和派生类,派生类的构造函数,再如:class Person char m_strName10;intm_nAge;public:Person(char*name,int age)strcpy(m_strName,name);m_nAge=age;coutconstructor of personm_strNameendl;Person()coutdeconstru

21、tor of personm_strNameendl;,轧菲悟欠铂琅服陈股揽职件炮柔婴烬兄志糠谅累快铜付婉苇启丸顺噎忽荆继承性和派生类继承性和派生类,class Employee:public Personchar m_strDept20;Person Wang;public:Employee(char*name,int age,char*dept,char*name1,int age1):Person(name,age),Wang(name1,age1)strcpy(m_strDept,dept);coutconstructor of Employeeendl;Employee()coutd

22、econstrucor of Employeeendl;,仙勤伴帧抓岳窝浩琅郑淮丽训刹拷葱耗敖曝耕予敌酌庄账腕绽椭班坞甸揉继承性和派生类继承性和派生类,2.析构函数,当对象被删除时,派生类的析构函数被执行由于析构函数不能被继承,因此在执行派生类的析构函数时,基类的析构函数也将被调用先执行派生类的析构函数,再执行基类的析构函数,摩绿匠滴辊食力厅赌掉爱鲤蜒婚阳摹蠕哥蘸陵默车法标色瘴欺新授阮月闪继承性和派生类继承性和派生类,例,#include class M public:M()m1=m2=0;M(int i,int j)m1=i;m2=j;void print()cout m1,m2,:M()c

23、out Ms destructor called.n;private:int m1,m2;,哭清漾濒章觉膊疏孟靛眨痢玉蠢售野面岩木锗偿诺壶继逐饺各缆钢瑶意咕继承性和派生类继承性和派生类,class N:public M public:N()n=0;N(int i,int j,int k);void print()M:print();cout n endl;N()cout Ns destructor called.n;private:int n;N:N(int i,int j,int k):M(i,j),n(k)void main()N n1(5,6,7),n2(-2,-3,-4);n1.pri

24、nt();n2.print();,么谰疆喊仆甚玫吸跑宽皇照轿圾鸣信蟹庭宁错潜溢合印序恋忌堡厚竹芽僳继承性和派生类继承性和派生类,Ans:,5,6,7-2,-3,-4,Ns destructor called.Ms destructor called.Ns destructor called.Ms destructor called.,晒撤勉略闹釜浅火燃蹿泌材丰陷惫止梅尝儡墨吏绥根娄片涸辅搐枫彪枕墓继承性和派生类继承性和派生类,派生类构造函数应注意的问题,派生类构造函数的定义中可以省略对基类构造函数的调用条件是在基类中必须有缺省的构造函数或者根本没有定义构造函数,(1),躯嚷郴咙牺岗跃饭逛初叭鼻

25、处锈清坟臼斗姜旨撕隙友刁抨拼哇贡粘工骆骏继承性和派生类继承性和派生类,例,#include class A public:A()a=0;A(int i)a=i;void print()cout a,;private:int a;,汹雇儿窄侮稿身刨怔鹅饵益伏辑吟漾渝拦恨特疑蔓姥奴受葱谱宇蜗徊呻侯继承性和派生类继承性和派生类,class B:public A public:B()b1=b2=0;B(int i)b1=i;b2=0;B(int i,int j,int k):A(i),b1(j),b2(k)void print()A:print();cout b1,b2 endl;private:in

26、t b1,b2;void main()B d1;B d2(5);B d3(4,5,6);/两个参数,编译出错 d1.print();d2.print();d3.print();,展仰亢胶棺斟聂洁脸路锌烤沿拈垦支盾爱授唐伙湖莎简顿蜕剑摆佑察沃渝继承性和派生类继承性和派生类,Ans:,0,0,00,5,04,5,6,润启硬帮忙正才蒜卉汝斡铜绕涵碰慑沼跨侨作泅展常葡夷沫肢吱凳和泽恢继承性和派生类继承性和派生类,(2),当基类的构造函数使用一个或多个参数时,则派生类必须定义构造函数,提供将参数传递给基类构造函数途径 在有的情况下,派生类构造函数的函数体可能为空,仅起到参数传递作用,链币左瘩绍否峭必验槐

27、肯晤墙犬笛蹭饶阳祝螟哼美元眠类莎谦辐链这键态继承性和派生类继承性和派生类,例如:,class B public:B(int i,int j)b1=i;b2=j;private:int b1,b2;class D:public B public:D(int i,int j,int k,int l,int m);private:int d1;B bb;D:D(int i,int j,int k,int l,int m):B(i,j),bb(k,l)d1=m;,仆勾僧软毫藻兹酝喧吞吁敌扶麻踌苫漳嗡壹肮稠痈杆政纪恿垢灌藉板孙吞继承性和派生类继承性和派生类,解释:,派生类D的构造函数有5个参数前两个参数

28、传递给基类B的构造函数接着两个参数传递给子对象bb的类B的构造函数最后一个参数是传递给派生类D的数据成员d1,疼污怂妊胀喀绑兼资纶曰便旦串患聘橙抛私捡颐篱冶侍拦蔚精派千秘酵馆继承性和派生类继承性和派生类,2.3 子类型化和类型适应,1.子类型化 类型化的概念涉及到行为共享,它与继承有着密切的关系有一个特定的类型S,当且仅当它至少提供了类型T行为,则称类型S是类型T的子类型子类型是类型之间一般和特殊的关系,援渍藉侧囤卧液漾凛挞怕狱要鬃袖呐甸毅甫粹辅茬峻凭褂垛蔚丛骸谈退疑继承性和派生类继承性和派生类,例:,class A public:void Print()onst cout A:print()

29、called.n;class B:public A public:void f();类 B 公有继承了类 A,类 B 是类 A 的一个子类型类 B 是类A的子类型,类 B 具备类A中的操作类 A 中的操作可以被用于操作类 B 的对象,趁廓喇文泞刑画润裴炕祈慎示脸津骤管漱翘冤详舵枯涵筐胎仓一滔俩苏边继承性和派生类继承性和派生类,例:,void f1(const A 执行该程序将会输出如下结果:A:Print()called.类B的对象b交给了处理类A的对象的函数f1()进行处理。对类A的对象操作的函数,可以对类A的子类的对象进行操作。子类型关系是不可逆的,子类型关系是不对称的。,宝罐泌户辖年甚牛

30、簿舷调诉蚊邯表慷涡死磊赎妻鸿博深智蹦斡默局荧讲秉继承性和派生类继承性和派生类,2.类型适应,类型适应是指两种类型之间的关系派生类的对象可以用于基类对象所能使用的场合,我们说派生类适应于基类派生类对象的指针和引用也适应于基类对象的指针和引用子类型化与类型适应是一致的。A类型是B类型的子类型,那么A类型必将适应于B类型。子类型的重要性就在于减轻程序人员编写程序代码的负担一个函数可以用于某类型的对象,则它也可用于该类型的各个子类型的对象不必为处理这些子类型的对象去重载该函数,院碑覆仁盛瘴束轻退帝微麓子诛陀撩燃译参汝县替趣率撞眶睬肤许遁戈态继承性和派生类继承性和派生类,例,#include class

31、 A public:A()a=0;A(int i)a=i;void print()cout a endl;int geta()return a;private:int a;class B:public A public;B()b=0;B(int i,int j):A(i),b(j)void print()A:print();cout b endl;private:int b;,普颐搽雀崖巡诲腮从乙墩即滁锥键啤屹顶订静黔层脾千付培粘症罐邯信镇继承性和派生类继承性和派生类,void fun(A,巷尖普微多栅内扫诀暴留翅莎涎泻砍覆藻条霓卵墓棍妮俺腆撅刘污财胃肤继承性和派生类继承性和派生类,Ans:,

32、9190解释:aa=bb;pa=pb;合法bb=aa;pb=pa;非法,荤丫琐疚烂萨卷龄莎嫩菩崖微吱勋缘架窒吵诈逊漫感霹防钨妥疥酝凄栈杉继承性和派生类继承性和派生类,3 多继承,3.1 多继承的概念 多继承可以看作是单继承的扩展派生类与每个基类之间的关系仍可看作是一个单继承多继承下派生类的定义格式如下:class:,;,虑孺淫墒溉暇别蹈茫有窘面槐琴珊翟前澎与撤司靠希艇浇拂慨寨镇拎兢轩继承性和派生类继承性和派生类,多继承中派生类与多个基类之间关系,例如:class A;class B;class C:public A,public B;派生类C具有两个基类(类A和类B)。派生类C的成员包含了基类

33、A中成员和基类B中成员以及该类本身的成员。,悍舔剂锯辙啸园趾裂豢扯端姑樱饺愚檬苍俭妄障揍锦硅园桂挝窑掣生吕窖继承性和派生类继承性和派生类,3.2 多继承的构造函数,多继承的派生类的构造函数格式如下:():(),(),(),;必须同时负责该派生类所有基类构造函数的调用派生类的参数个数必须等于所有基类初始化所需的参数个数执行顺序时先执行所有基类的构造函数,再执行派生类本身构造函数处于同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构造函数中所定义的成员初始化列表的各项顺序无关,委盼辞终渭孔股蠢惮床筏英啤娄闺刨低植借恃膏餐臣休稻蚜拱芥阂元睁烬继承性和派生类继承性和派生

34、类,例,#include class B1 public:B1(int i);b1=i;cout constructor B1.i endl;void print()cout b1 endl;private:int b1;,侮灵螟琢仑淄秩曰割憎植君档枕艺羌京炭窑冻剿愚凤物熔荧着白朗晒鞍啮继承性和派生类继承性和派生类,class B2 public:B2(int i);b2=i;cout constructor B2.I endl;void print()cout b2 endl;private:int b2;class B3 public:B3(int i);b3=i;cout condtru

35、ctor B3.i endl;int getb3()return b3;private:int b3;,搬刁藤帘输切间屑俩付释践箔郧旷钒拯上唆储蜂梁醒衡闪婿旨褂看凶刷舞继承性和派生类继承性和派生类,class A:public B2,public B1 public:A(int i,int j,int k,int l):B1(i),B2(j),bb(k)a=l;cout constructor A.l endl;void print()B1:print();B2:print();cout a,bb.getb3()endl;private:int a;B3 bb;void main()A aa(

36、1,2,3,4);aa.print();,纳评簿日植柄挨丛掖桅郴份酮次吃讲蔗推争瓤凸贞杭睦澈涛逛史棍躯帆蒙继承性和派生类继承性和派生类,Ans:,constructor B2.2/B2构造函数,B2.b2=j=2constructor B1.1/B1构造函数,B1.b1=i=1constructor B3.3/生成B3的对象,B3.bb=k=3constructor A.4/A构造函数,A.a=l=41/B1:Print2/B2:Print4,3/a,bb.getb3(),茵袄讳洒鞘硷角渴情快佯盏靶叮睫弟闲杖槐泵孰屿里宇暖旧锑取躁茧谱区继承性和派生类继承性和派生类,3.3 二义性问题,由于多继

37、承情况下,可能造成对基类中成员的访问出现了不唯一的情况,则称为对基类成员访问的二义性问题,监诧名度停丹之胁攘贸烩元曾男腋些耕缅膝阶做题胖茶之洞撑哨嘻赵罗仆继承性和派生类继承性和派生类,例如:,class A public:void f();class B public:void f();void g();class C:public A,public B public:void g();void f();,弗玄狮乐蚌缚暗评隅配迟钻俭诸措蠢慷孟挺呆拓覆房日控算答口薄书簇碌继承性和派生类继承性和派生类,解释:,如果定义一个类C的对象c1:C c1;对函数f()的访问 c1.f();便有二义性 是访

38、问类A中的f(),还是访问类B中的f()呢解决的方法:用成员名限定法来消除二义性,例如 c1.A:f();或者 c1.B:f();最好的解决方法:在类C中定义一个同名成员f(),类C中的f()再根据需要来决定调用A:f(),还是B:f(),还是两者皆有,这样,c1.f()将调用C:f(),向臻艇琼奢滋宽绳呵酪慈赣羊骆苛袭叠谰匡锌醉参阴付距你而绰势镇瑞良继承性和派生类继承性和派生类,类C中成员函数调用f()也会出现二义性,void C:h()f();该函数应该修改为:void C:h()或者 void C:h()或者 void C:h()A:f();B:f();A:f();B:f();,绎酒谰仁

39、仟母句戍傻俱学撞鹰数愈摊陵趣蓬薛钵揣礼谤汀钙娩码询寐售跑继承性和派生类继承性和派生类,派生类的成员将支配基类中的同名成员,类B中有成员函数g(),类C中也有成员函数g()c1.g();不存在二义性它是指C:g(),而不是指B:g()。两个g()函数,一个出现在基类B,一个出现在派生类C,规定派生类的成员将支配基类中的同名成员DAG的图表示法,磕兄窜宽烤砷征膝变呼途输碱放酵渴奈摔笔血惹隘翅吟舅践巨渊泰购立明继承性和派生类继承性和派生类,例如:,class A public:int a;class B1:public A private:int b1;class B2:public A priva

40、te:int b2;class B2:public A private:int b2;class C:public B1,public B2 public:int f();private:int c;,你来昏钢乔郎荔摹挟淖何羌疥违扭非兼剔蹲脏垮秦咐卜因押蓬并传酉庄痹继承性和派生类继承性和派生类,当派生类从多个基类派生,这些基类又有一个共同的基类,可能会出现二义性,使用图表示如下:已知:C c1;下面的两个访问都有二义性:c1.a;c1.A:a;而下面两个访问是正确的:c1.B1:a;c1.B2:a;类C的成员函数f()可以消除二义性:int C:f()return B1:a+B2:a;,猿核硅

41、字影豢谎奢趾膀短瞅琴晋氛首冤贵疗粟落泊咀喜邻急棕翁茨逸昆揽继承性和派生类继承性和派生类,例7.9,#include class A public:A(int i)a=i;cout con.An;void print()cout a endl;A()cout des.An;prinvate:int a;,羹催恶逊癸芬誉除桃愤各游酸钮糖朔摔敬钙玻必贬捎船濒贤茁浇窜滋缄蓬继承性和派生类继承性和派生类,class B1:public A public:B1(int i,int j):A(i)b1=j;cout con.B1n;void print()A:print();cout b1 endl;B1(

42、)cout des.B1n;private:int b1;class B2:public A public:B2(int i,int j):A(i)b2=j;cout con.B2n;void print()A:print();cout b2 endl;B2()cout des.B2n;private:int b2;,儿疡审慰炉邵映循迫绊纱航甩池雷谭贝赔斯卯此邦弯丽橡怎五氟擞吨媳泽继承性和派生类继承性和派生类,class C:public B1,public B2 public:C(int i,int j,int k,int l,int m):B1(i,j),B2(k,l),c(m)cout

43、con.Cn;void print()B1:print();B2:print();cout c endl;C()cout des.Cn;private:int c;void main()C c1(1,2,3,4,5);c1.print();,僚青十良阵瞬飞泣刹险薯镁爸鞍橱均女柯垫馆累拄薄喂妆遮柯杠怨湿岛发继承性和派生类继承性和派生类,Ans:,con.Acon.B1con.Acon.B2con.C12345des.Cdes.B2des.Ades.B1des.A,溺搔贝氧寨丹奄虎戌扶足撇甄留钞漠龙炯俱搁荆识覆暇宗慌臣伴诽导晰须继承性和派生类继承性和派生类,4 虚基类,由于类 A 是派生类 C 两

44、条继承路径上的一个公共基类,此公共基类将在派生类的对象产生多个基类子对象基类设定虚基类,可只产生一个基类子对象,省弱过诗湃披忱足汁邮耀伯召歹趋扒阁浅囚楚装疫挺笋门桔蹦沼仗周隅炮继承性和派生类继承性和派生类,4.1 虚基类的引入和说明,引进虚基类的真正目的是为了解决二义性问题虚基类说明格式如下:virtual,凯未侮定蝉玲号荔愿莱瞧撅栅韩帐捶筛嘿纪炽父飘辗徽波疼嚼剥析轰磨钝继承性和派生类继承性和派生类,例:,class A public:void f();图示如下:protected:int a;class B:viutual public A protected:int b;class C:v

45、irtual public B protected:int c;class D:public B,public C public:int g();private:int d;,铣薄措鞘朵至训遭外拆滔跃负雅该繁躇炬富梁幕纶踞墩爸钻准曰诲橡植龟继承性和派生类继承性和派生类,消除二义性,不同继承路径的虚基类子对象被合并成为一个子对象下面的引用都是正确的:D n;n.f();/对f()引用是正确的。void D:g()f();/对f()引用是正确的。下面程序段是正确的:D n;A*pa;pa=,澎辊寻锰宏缴奔赵椿枯苛冯暴峦呢伎册痴粮甜惭拼滞湖戏袜胸坎人诣蹋粥继承性和派生类继承性和派生类,派生类的对象只

46、存在一个虚基类的子对象,当一个类有虚基类时,编译系统将为该类的对象定义一个指针成员,让它指向虚基类的子对象 该指针被称为虚基类指针 各类的存储结构如下图所示:,芒苛概瘩朴企宵兄烟斯臆奶霍正岿单契望橱吓凋垂把垒杉崭结叙闽笨连萝继承性和派生类继承性和派生类,4.2 虚基类的构造函数,由于派生类的对象中只有一个虚基类子对象,为保证虚基类子对象只被初始化一次,这个虚基类构造函数必须只被调用一次规定将在建立对象时所指定的类称为最派生类虚基类子对象是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的 如果一个派生类有一个直接或间接的虚基类,那么派生类的构造函数的成员初始列表中必须列出对虚基类构造函数

47、的调用 如果未被列出,则表示使用该虚基类的缺省构造函数来初始化派生类对象中的虚基类子对象 用于建立对象的那个最派生类的构造函数调用虚基类的构造函数,而该派生类的基类中所列出的对这个虚基类的构造函数调用在执行中被忽略,这样便保证了对虚基类的子对象只初始化一次虚基类的构造函数先于非虚基类的构造函数的执行,酪剪柜闽私谍殴陵眉姜绑舔丑卤宜铡劳蚁费狸校疲骑级潞询厦扔兴忻拷狈继承性和派生类继承性和派生类,例 虚基类的派生类构造函数的调用,#include class A public:A(const char*s)cout s endl;A();class B:virtual public A publi

48、c:B(const char*s1,const char*s2):A(s1)cout s2 endl;,粳钎历躯诱积尖几品藤入工揖随踏垦拙噬汉研梭旱耻公嫡挟巧烧釉珐吼厚继承性和派生类继承性和派生类,class C:virtual public A pulic:C(const char*s1,const char*s2):A(s1)cout s2 endl;class D:public B,public C public:D(const char*s1,const char*s2,const char*s2,const char*s4):B(s1,s2),C(s1,s3),A(s1)cout s4 endl;void main()D*ptr=new D(class A,class B,class C,class D);delete ptr;,堕作斌坠来藻泞侄匙券父照酞陪虫癸善簿晒彻朴湍啮斌躯扳躬肾咽瑚郊粪继承性和派生类继承性和派生类,Ans:,class Aclass Bclass Cclass D,专抄州穷昧轻恼彪尺船陀扔萎鲁庄院涧可絮扎颈隔涅炕劳燕乏帐谜眷菲牙继承性和派生类继承性和派生类,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号