- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第9章 继承机制.ppt
四 多重继承 当一个派生类具有多个基类时,称这种派生为多重继承或多基派生。如下图: * 定义多重继承类的方式如下: class 派生类名:访问方式 基类名,访问方式 基类名…… { …… }; 其中:访问方式为public、protected或private。 如在程序中大量使用的iostream提供的服务,这个库中的多个类就是应用了多重继承,输入/输出流同时具有输入流和输出流的特征,因而iostream同时继承了istream和ostream两个类。(可查看系统库中的文件iostream.h) * istream ostream iostream 多种继承中的主要问题是标识不唯一。比如,在派生类继承的这多个基类中有同名成员时,派生类中就会出现来自不同基类的同名成员,就出现了标识不唯一或二义性的情况,这在程序中是不允许的。例如: * * class base1 { public: int x; int a(); int b(); int b(int); int c(); }; class base2 { int x; int a(); public: float b(); int c(); }; class derived:base1,base2 { }; void d(derived e) { e.x=10; //错误,x有二义性 e.a(); //错误,有二义性 e.b(); //错误,有二义性 e.c(); //错误,有二义性 } 解决这个问题的办法有三种, 一是使用作用域运算符“∷”, 二是使用同名覆盖的原则, 三是使用虚函数。 1.使用作用域运算符 如果派生类的基类之间没有继承关系,同时又没有共同的基类,则在引用同名成员时,可在成员名前加上类名和作用域运算符“∷”,来区别来自不同基类的成员。例如,将例9.8中的函数d(derived e)改写如下,就不会出现这个问题了: void d(derived e) { e.base1::x=10; e.base2::a(); e.base2::b(); e.base1::c(); } * 2.使用同名覆盖的原则 在派生类中重新定义与基类中同名的成员(如果是成员函数,则参数表也要相同,参数不同的情况为重载)以隐蔽掉基类的同名成员,在引用这些同名的成员时,使用的就是使用派生类中的函数,也就不会出现二义性的问题了。例如: * class base { public: int x; void show() {cout”This is base, x=”xendl; }; class derived:base { public: int x;//同名数据成员 void show() //同名成员函数 { cout”This is derived, x=”xendl; }; void main() { derived ob; ob.x=5; //用同名覆盖原则引用派生类数据成员 ob.show(); //用同名覆盖原则引用派生类成员函数 ob.base::x=12; //用作用域运算符访问基类成员 ob.base::show(); //用作用域运算符访问基类成员 } 2、多重继承的构造函数和析构函数 声明多继承构造函数的一般形式为: 派生类名::派生类名(参数总表):基类名1(参数表1),…,基类名n(参数表n),对象成员名1(对象成员参数表1),…,对象成员名m(对象成员参数表m) { //派生类新增成员的初始化语句 } * 其中: ⑴ 派生类的构造函数名与派生类名相同。 ⑵ 参数总表列出初始化基类成员数据、新增对象成员数据和派生类新增成员数据所需要的全部参数。 ⑶ 冒号后列出需要使用参数进行初始化的所有基类的名字和所有对象成员的名字及
文档评论(0)