一.单继承 –多态性

二.多继承- 二义性ambiguous

  1. 多个直接父类中  出现同名成员时产生的二义性
  2. 同一个父类  通过不同继承路径产生的二义性

例8-6    A1父类中的f1(),还是A2父类中的f1()

#include <iostream>

using namespace std;

class A1

{   public:

void f1()

{          cout<<"A1类中的函数f1()"<<endl;  }

};

class A2

{   public:

void f1()

{           cout<<"A2类中的函数f1()"<<endl;   } // 该成员与A1中的重名

};

class B:public A1,public A2

{

};

int main()

{

B b;

b.f1();    // 该句出错

}

#include <iostream>

using namespace std;

class A1

{   public:

void f1()

{          cout<<"A1类中的函数f1()"<<endl;  }

};

class A2

{   public:

void f1()

{           cout<<"A2类中的函数f1()"<<endl;   } // 该成员与A1中的重名

};

class B:public A1,public A2

{

};

int main()

{

B b;

b.A1::f1();    // 作用域运算符

b.A2::f1();

}

#include <iostream>

using namespace std;

class A1

{   public:

void f1()

{          cout<<"A1类中的函数f1()"<<endl;  }

};

class A2

{   public:

void f1()

{           cout<<“A2类中的函数f1()”<<endl;    // 该成员与A1中的重名     }

void f2()

{        cout<<"A2类中的函数f2()"<<endl;       }

};

class B:public A1,public A2

{   public:

void f2()

{        cout<<"派生类B中的函数f2()"<<endl;        }    //  与基类A2中的成员同名

void f3()

{        cout<<"派生类B中的函数f3()"<<endl;      }

};

void main()

{  B b;

b.f1();    // 该句出错

b.f2();

b.f3();

}

程序在编译时会出错,错误信息如下:

error C2385: 'B::f1' is ambiguous

warning C4385: could be the 'f1' in base 'A1' of class 'B'

warning C4385: or the 'f1' in base 'A2' of class 'B'

A1类中有一个函数成员f1(),A2类中也有一个同名的函数成员f1(),

派生类B中继承了这两个同名的成员,

类B的对象b对f1()的访问b.f1()出现了二义性,无法确定访问A1类中的f1(),还是A2类中的f1()?

解决方法:

使用作用域运算符“::”明确指出访问的是从哪个类中继承的成员。

例如:将b.f1()写成b.A1::f1();或b.A2::f1();

程序中,A2类和B类中还有一个同名的函数成员f2(),但b对f2的访问b.f2();在编译时并没有出错。

在类的继承层次结构中,基类和派生类具有包含关系,派生类在内层,基类在外层。

同名覆盖

具有包含关系的两个或多个作用域,如果在外层中声明的标识符在内层中没有同名标识符,则它在内层可见,如果内层中声明了同名标识符,则外层标识符在内层不可见,也就是内层标识符覆盖了外层的同名标识符

B类和A1类、B类和A2类都具有包含关系,对于B类和A2类,A2类在外层,B类在内层,这样,根据可见性原则,可知b.f2()访问的是B类的f2()

void main()

{  B b;

  b.A1::f1();

  b.A2::f1();

  b.f2();

  b.f3();

}

这时,没有出现二义性

多层继承中  使用作用域运算符==延伸例8-7

#include <iostream>

using namespace std;

class A

{   public:

         void fun()

         {          cout<<"A类的函数fun()"<<endl;  }

};

class B:public A

{   public:

         void fun()  {  cout<<"B类的函数fun()"<<endl;}

};

class C:public B

{   public:

         void fun()  {  cout<<"C类的函数fun()"<<endl;    }

};

class D:public C

{   public:

         void f()     { C::fun(); B::fun();   A::fun();         }

};

void main()

{        D d;

         d.f();

}

8-8如果一个派生类C 多个基类B1 B2派生,而这些基类又有一个共同的老基类A,当对该老基类A中说明的成员进行访问时,也可能出现的二义性

#include <iostream>

using namespace std;

class A

{  public:

void fun()

{      cout<<"A类的函数fun()"<<endl;     }

};

class B1:public A

{    };

class B2:public A

{    };

class C:public B1,public B2

{     };

void main()

{        C c;

c.fun();

}

程序在编译时出错,错误信息如下:

error C2385: 'C::fun' is ambiguous

warning C4385: could be the 'fun' in base 'A' of base 'B1' of class 'C'

warning C4385: or the 'fun' in base 'A' of base 'B2' of class 'C'

图(b)中,类C继承两个基类B1和B2,而B1和B2又有一个共同的基类A,这样,类A是派生类C在两条继承路径上的公共基类,这个公共基类在派生类C的对象中将包含两个基类A的子对象,从而导致对基类成员访问时的不唯一性,

将基类A定义为虚基类,能够使得公共基类A在派生类中只产生一个子对象,就可避免二义性问题

法(一)作用域运算符

#include <iostream>

using namespace std;

class A

{      public:

void fun()     {   cout<<"A类的函数fun()"<<endl;          }

};

class B1:public A { };

class B2:public A { };

class C:public B1,public B2  {  };

main()

{        C c;

c.B1::fun();

c.B2::fun();

}

法(二)虚基类

#include <iostream>

using namespace std;

class A

{      public:

            void fun()    {   cout<<"A类的函数fun()"<<endl;       }

};

class B1:virtual public A { };

class B2:public virtual A { };

class C:public B1,public B2  {  };

void main()

{        C c;

          c.fun();

}

单继承--多态性 多继承--二义性 ambiguous相关推荐

  1. Python 在子类中调用父类方法详解(单继承、多层继承、多重继承)

    Python 在子类中调用父类方法详解(单继承.多层继承.多重继承)   by:授客 QQ:1033553122   测试环境: win7 64位 Python版本:Python 3.3.5 代码实践 ...

  2. python中的单继承,多继承和mro顺序

    python作为一门动态语言,是和c++一样支持面向对象编程的.相对对象编程有三大特性,分别是继承,封装和多态.今天我们重点讲解的是,python语言中的单继承和多继承. 继承概念: 如果一个类继承了 ...

  3. Python OOP:继承、单继承、多继承、__mro__、子类重写父类同名属性和方法、子类调用父类同名属性和方法、多层继承、super()、私有(实例)属性和方法、获取修改私有属性值、私有类属性

    一.继承 Python⾯向对象的继承指的是多个类之间的所属关系,即⼦类默认继承⽗类的所有属性和⽅法. 继承作用:继承可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展. 在P ...

  4. C++对象模型:单继承,多继承,虚继承

    什么是对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分. 对于各种支持的底层实现机制. 类中成员分类 数据成员分为静态和非静态,成员函数有静态非静态以及虚函数 cla ...

  5. Java_单继承和多继承

    1 /* 2 继承: 3 好处:提高了代码的复用性,让类与类之间产生了关系. 4 将对象中的共性内容不断的向上抽取,就形成了关系,就有了继承,有了子父类, 5 提高了代码的复用 6 7 继承特点: 8 ...

  6. java单继承和多继承

    java单继承和多继承 单线程:一个子类只能继承自一个父类 多线程:一个子类可以继承自多个父类 java继承关键字extend和implement,Java所有子类都继承自 java.lang.Obj ...

  7. C++ - 多态(2) | 虚表的打印、单继承与多继承的虚表

    之前的文章中我们介绍了多态的原理以及虚表的知识,本文中我们将继续对多态进行更加深入的学习. 单继承中的虚函数表 虚函数表(虚表)的本质是一个函数指针数组,虚函数的地址会进入虚表.首先我们来看一下这样的 ...

  8. 简明阐述Java到底是单继承还是多继承?

    一.先上结论: 这个问题要分为类和接口两种情况来谈. 即Java中支持的是类的单继承以及接口的多继承(不过其实我们通常对于接口会说实现,而不是继承).所以也会有'Java中支持的是类的单继承以及接口的 ...

  9. iOS严谨单例写法/可继承单例

    单例模式在iOS开发中可能算是最常用的模式之一了,但是由于OC本身的语言特性,想要写一个正确的单例模式相对来说比较麻烦. 今天就来说一说, 单例创建的方式和严谨的单例写法及可继承单例编写. 基本单例的 ...

最新文章

  1. 德国版“非升即走”引发学界震荡!“临时工”干12年也难获教职,网友:全世界都在卷...
  2. 快速搭建一个网关服务,动态路由、鉴权看完就会(含流程图)
  3. 第十六届全国大学生智能车竞赛全部比赛胜利结束了
  4. 路由器启动后如何定位IOS?
  5. logisim无法打开解决办法
  6. 带你自学Python系列(十三):Python函数的用法(三)
  7. 通过jquer连接数据库里面的数据、LINQ简介
  8. 为什么阿里巴巴的市值比京东高,世界500排名比京东靠后?
  9. PCA算法的原理C++ Eigen库实现(附源码下载)
  10. VRTK HTC手柄发出射线,瞬移,选择物体 VRTK和steamVR对应版本
  11. dos批处理文件中使用vbs
  12. 三菱PLC传送类指令应用
  13. 联通的G网和C网分别是什么意思?
  14. dubbo之@Adaptive注解分析
  15. Android 内部存储和外部存储
  16. 一个dht网络的“磁力链接”搜索python代码
  17. PLSQL执行SQL脚本文件「适用批量」- 工具使用篇
  18. 硬件开发者之路之运放共模电压的解释
  19. day 63 Django基础九之中间件
  20. linux录屏和截图软件

热门文章

  1. Deep Learning for 3D Point Clouds: A Survey 论文阅读
  2. RGB图像重建非刚性物体三维形状(CVPR)
  3. 时空穿越!谷歌利用众包老照片还原儿时3D街景,浏览器即可体验
  4. 吊打一切的YOLOv4的tricks汇总!附参考论文下载
  5. React + Threejs + Swiper 实现全景图效果
  6. iclr 2020 | Geom-GCN:几何图神经网络
  7. LaTeX 中表格的用法总结(四)——三线表和复杂的表格
  8. 遗传:细菌、真菌和动植物的泛基因组研究进展
  9. 134人!国家重点研发计划“生物大分子与微生物组”重点专项会评专家名单
  10. 易生信高级转录组分析和数据可视化-最后一天报名