《(5.4)--第5章继承 - (04)_多继承面向对象程序设计.ppt》由会员分享,可在线阅读,更多相关《(5.4)--第5章继承 - (04)_多继承面向对象程序设计.ppt(15页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、面向对象程序设计第5章 继 承多继承多继承01.多继承的概念多继承的概念02.多继承中的二义性多继承中的二义性03.二义性的解决方法二义性的解决方法第章继承多继承1.多继承的概念多继承的概念在现实生活中,很多继承均表现为在现实生活中,很多继承均表现为多重继承。多重继承。一个派生类可以有多个直接基类,一个派生类可以有多个直接基类,则这种继承方式称为则这种继承方式称为多继承,多继承,或或称为称为多重继承多重继承派生类与每一个基类之间关系派生类与每一个基类之间关系可以看作是一个单继承。可以看作是一个单继承。l多继承时派生类的声明多继承时派生类的声明class 派生类名:继承方式派生类名:继承方式1
2、基类名基类名1,继承方式继承方式2 基类名基类名2,.成员声明;成员声明;注意:注意:每一个每一个“继承方式继承方式”,只,只用于限制对紧随其后之基类的用于限制对紧随其后之基类的继承。继承。多继承的构造函数调用顺序多继承的构造函数调用顺序l派生类的构造函数须同时负责该派生派生类的构造函数须同时负责该派生类所有基类构造函数的调用。类所有基类构造函数的调用。l构造函数调用顺序是:先调用所有基构造函数调用顺序是:先调用所有基类的构造函数,再调用派生类的构造类的构造函数,再调用派生类的构造函数。函数。l处于同一层次的各基类构造函数的调处于同一层次的各基类构造函数的调用顺序取决于定义派生类所指定的基用顺
3、序取决于定义派生类所指定的基类顺序,与派生类构造函数中所定义类顺序,与派生类构造函数中所定义的成员初始化列表顺序无关。的成员初始化列表顺序无关。多继承的析构函数的调用顺序多继承的析构函数的调用顺序l执行派生类的析构函数;执行派生类的析构函数;l按照子对象声明的相反顺序依次调用按照子对象声明的相反顺序依次调用子对象的析构函数;子对象的析构函数;l按照基类声明的相反顺序依次调用各按照基类声明的相反顺序依次调用各基类的析构函数基类的析构函数第章继承多继承【例【例5-7】多继承方式下构造函数的调用顺序。】多继承方式下构造函数的调用顺序。#include using namespace std;clas
4、s Base1 public:Base1(int i)a=i;coutconstructing Base1 a=aendl;private:int a;class Base2 public:Base2(int i)b=i;coutconstructing Base2 b=bc=c;coutconstructing Derivedclass c=cendl;int main()Derivedclass x(5,6,7);return 0;constructing Base1 a=6constructing Base2 b=5constructing Derivedclass c=7Press a
5、ny key to continue程序运行结果:第章继承多继承base1base2derivedbase 当在派生类中访问共同基类的成员时,可能有二义性当在派生类中访问共同基类的成员时,可能有二义性第章继承多继承class Basepublic:int b;void f();class Base1:public Baseprivate:int b1;class Base2:public Baseprivate:int b2;class Derived:public Base1,public Base2public:int f();private:int d;如果声明:如果声明:Derived
6、 p;有二义性有二义性p.b;p.Base:b无无二义性二义性p.Base1:bp.Base2:b 2.二二义性问题义性问题bb1bb2dBase类成员Base类成员Base1类成员Base2类成员Derived类对象第章继承多继承各类包含的数据成员各类包含的数据成员l解决方法一:用类名来限定解决方法一:用类名来限定如:如:p.Base1:b或或 p.Base2:b。l解决方法二:同名隐藏解决方法二:同名隐藏如:如:在在Derived类中声明一个同名的公有成员中声明一个同名的公有成员函函数数f()。l解决方法三:虚基类解决方法三:虚基类第章继承多继承3.二义性问题解二义性问题解决决方法方法本小
7、节结束谢谢谢谢大大家家【例【例5-9】派生类覆盖基类中的同名成员】派生类覆盖基类中的同名成员#include using namespace std;class Base1 public:int i;void fun()cout Base1的fun函数被调用 endl;class Base2 public:int i;void fun()cout Base2的fun函数被调用 endl;class Derived:public Base1,public Base2 public:int i;void fun()cout Derived的fun函数被调用 endl;int main()Deriv
8、ed d;Derived*p=&d;d.i=1;d.fun();return 0;同名数据成员同名数据成员同名函数成员同名函数成员程序运行结果:程序运行结果:Derived的的fun函数被调用函数被调用第章继承多继承拍摄不用此页拍摄不用此页【例例】多重继承派生类构造函数和析构函数#include using namespace std;class Base1 public:Base1(int i)coutconstructing Base1 iendl;Base1()coutdestructing Base1 endl;class Base2 public:Base2(int j)coutco
9、nstructing Base2 jendl;Base2()coutdestructing Base2 endl;class Base3 public:Base3()coutconstructing Base3*endl;Base3()coutdestructing Base3 endl;class Derived:public Base2,public Base1,public Base3 public:Derived(int a,int b,int c,int d):Base1(a),memberA2(d),memberA1(c),Base2(b)private:Base1 memberA
10、1;Base2 memberA2;Base3 memberA3;int main()Derived obj(1,2,3,4);return 0;constructing Base2 2constructing Base1 1constructing Base3*constructing Base1 3constructing Base2 4constructing Base3*destructing Base3destructing Base2destructing Base1destructing Base3destructing Base1destructing Base2第章继承多继承拍
11、摄不用此页拍摄不用此页2.二义性问题二义性问题在多重继承中,派生类对基类成员访问在下列两种情况下可能出现二义性。访问不同基类的相同名成员同名成员时可能出现二义性访问共同基类共同基类中成员时可能出现二义性多重继承可以反映现实生活中的情况,能够有效地处理一些较复杂的问题,使编写程序具有灵活性,充分体现了软件重用的优点,但是由于多重继承方式下,派生类可能有多个直接基类或间接基类,可能造成对基类中某个成员的访问出现了不确定的情况,使得这种访问具有二义性。AB1B2Dg(),j()f()A类类B1类类g(),h()B2类类D类类g(),p()如果声明:如果声明:D c1;调用哪个函数时会产调用哪个函数时
12、会产生二义性的问题?生二义性的问题?则则c1.f();具有二义性具有二义性而而c1.g();无二义性(同名隐藏)无二义性(同名隐藏)第章继承多继承拍摄不用此页拍摄不用此页3.二义性问题解决二义性问题解决通常有两种方法:通常有两种方法:(1)成员名限定成员名限定 通过类的作用域限定符通过类的作用域限定符(:)明确限定出现二义性的成员是继承自哪一个基明确限定出现二义性的成员是继承自哪一个基类。类。(2)成员重定义成员重定义 在派生类中新增一个与基类中成员相同的成员,由于在派生类中新增一个与基类中成员相同的成员,由于同名覆盖同名覆盖,程序将自,程序将自动选择派生类新增的成员。动选择派生类新增的成员。
13、一是使用作用域运算符。二是将直接基类的共同基类设置为虚基类。直接基类名直接基类名:数据成员名数据成员名 直接基类名直接基类名:成员函数名(参数表)成员函数名(参数表)第章继承多继承拍摄不用此页拍摄不用此页#include using namespace std;class B1 protected:int b1,m;public:B1()b1=3;m=4;class B2 protected:int b2,m;public:B2()b2=5;m=6;class D:public B1,public B2int d,m;public:D()d=7;m=8;void show()coutB1:b1tb2tdn;coutB1:mtB2:mtmn;int main()D test;test.show();return 0;335 5 74 4 6 6 8 8testB1:b1=3B1:m=4B2:b2=5B2:m=6D:d=7D:m=8程序运行程序运行结果果第章继承多继承拍摄不用此页拍摄不用此页