在C++中,派生类继承基类,对基类成员的访问应该是确定的、唯一的,但是常常会有以下情况导致访问不一致,产生二义性。
    1.在继承时,基类之间、或基类与派生类之间发生成员同名时,将出现对成员访问的不确定性——同名二义性。
    2.当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生另一种不确定性——路径二义性。

    1.

“倒三角”问题——同名二义性

#include "iostream"using namespace std;class Parent_f
{
public:void show(){cout<<"This is Parent_f\n";}
};
class Parent_m
{
public:void show(){cout<<"This is Parent_m\n";}
};
class Son:public Parent_f,public Parent_m
{
public:void display(){cout<<"This is son\n";}
};
int main()
{Son son;son.show();son.display();cout << "Hello world!" << endl;return 0;
}

上面的代码中,2个父类派生一个子类,但两个父类中都有同名的成员函数。派生出的子类产生二义性问题,编译时会报:

error: request for member 'show' is ambiguous

解决方法:

(1)利用作用域限定符(::),用来限定子类调用的是哪个父类的show()函数

son.Parent_f::show();

(2)在类中定义同名成员,覆盖掉父类中的相关成员

class Son:public Parent_f,public Parent_m
{
public:void display(){cout<<"This is son\n";}void show(){cout<<"show:This is son.\n";}
};

2.

“菱形”问题——路径二义性

有最基类A,有A的派生类B、C,又有D同时继承B、C,那么若A中有成员a,那么在派生类B,C中就存在a,又D继承了B,C,那么D中便同时存在B继承A的a和C继承A的a,那么当D的实例调用a的时候就不知道该调用B的a还是C的a,就导致了二义性。

#include "iostream"using namespace std;class Grandpa
{
public:int year_old;
};class Parent_f:public Grandpa {};
class Parent_m:public Grandpa {};class Son:public Parent_f,public Parent_m {};int main()
{Son son;son.year_old = 10;cout << "Hello world!" << endl;return 0;
}

Grandpa为Parent_f和Parent_m的基类,而Son又继承Parent_f和Parent_m,当Son访问Grandpa的year_old时,会出现二义性错误.

解决方法:

(1)使用作用域限定符,指明访问的是哪一个基类的成员。

注意:不能是Grandpa作用域下限定,因为Son直接基类的基类才是Grandpa,纵使指明了访问Grandpa的成员的话,对于Son来说,还是模糊的,还是具有二义性。

(2)在类中定义同名成员,覆盖掉父类中的相关成员。

(3)虚继承、使用虚基类

教科书上面对C++虚基类的描述玄而又玄,名曰“共享继承”,名曰“各派生类的对象共享基类的的一个拷贝”,其实说白了就是解决多重多级继承造成的二义性问题。父类对祖父类的继承方式改为虚继承,那么子类访问自己从祖父类那里继承过来的成员就不会有二义性问题了,也就是将子类对象里的祖父类对象统一为一个,继承的只有一个祖父类对象,代码如下。

#include "iostream"using namespace std;class Grandpa
{
public:int year_old;void show(){cout << "year_old:" << year_old <<endl;}
};class Parent_f:virtual public Grandpa {};
class Parent_m:virtual public Grandpa {};class Son:public Parent_f,public Parent_m {};int main()
{Grandpa grp;Parent_f pa_f;Parent_m pa_m;Son son;grp.year_old = 100;pa_f.year_old = 55;pa_m.year_old = 50;son.year_old = 10;grp.show();pa_f.show();pa_m.show();son.show();cout << "Hello world!" << endl;return 0;
}

使用了虚基类的方法,是不是感觉简单方便多了呢

C++多继承中的二义性问题相关推荐

  1. 什么叫虚继承(虚拟继承)?如何消除继承中的二义性?

    乍听虚继承,吓倒很多人!! 或许很多人会认为这和虚函数有关,其实,几乎没有任何关系.它的出现,是为了克服继承中一个非常棘手的问题,也就是臭名昭著的菱形继承(二义性)问题. 二义性,也就是说,假如我们有 ...

  2. c++抽象类在多继承中的应用

    面向接口编程和C++多态 前言 有关多继承的说明 多继承中的二义性和多继承不能解决的问题 多继承的应用场景 实际工程经验证明 子类需要根据功能说明定义功能实现. 前言 C++中没有Java中的接口概念 ...

  3. 在保护继承中基类的共有成员_C++学习大纲:继承方式的调整

    C++ 继承方式的调整 在任何继承方式中,除了基类的private成员外,都可以在派生类中分别调整其访问控制. 调整格式 [public: | protected: | private: ] :: ; ...

  4. C++对象继承中的内存布局

    虚函数表 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的.简称为V-Table.在这个表中,主是要一个类的虚函数的地址表 ...

  5. C++虚继承中的虚基类表

    虚继承主要解决多重继承会在子类中存在多份拷贝的问题,这不仅浪费空间,而且存在二义性. 在之前的 C++ 继承中已经说过虚继承基本概念,这里不再赘述.这篇文章主要探究虚继承的原理.文章中多处给出了类实例 ...

  6. C++继承中构造函数、析构函数调用顺序及虚析构函数

    首先说说构造函数,大家都知道构造函数里就可以调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就可以调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数, ...

  7. 关于学习Python的一点学习总结(33->继承中内置方法及多继承)

    73.继承中的一些内置方法: 1. issubclass(类1,类2):判断一个类是不是另一个类的子类: 2. 类名. _ bases _ :访问一个类的特殊属性: 3. isinstance(对象, ...

  8. C++继承中析构函数 构造函数的调用顺序以及虚析构函数

    首先说说构造函数.大家都知道构造函数里就能够调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就能够调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数, ...

  9. 《java入门第一季》之面向对象面试题(继承中构造方法的关系)

    /*继承中构造方法的关系A:子类中所有(子类的有参和无参)的构造方法(默认都会访问父类)中(空参数)的构造方法,默认访问父类空参数构造,不默认访问有参数构造B:为什么呢?因为子类会继承父类中的数据,可 ...

最新文章

  1. Qt写ini配置文件
  2. CTFshow 命令执行 web120
  3. python高斯滤波和降噪_高斯滤波原理及python实现
  4. 使用Regions ADF 11g进行Master Detail CRUD操作
  5. 2.2线性表的顺序表示和实现
  6. 动态规划-矩阵连乘问题
  7. [Hash应用问题] 例3.2 给出n个整数,按从大到小的顺序输出前m大的数
  8. [转]MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  9. linux增加datavg的大小,linux lvm扩容
  10. opencv (五十四)ORB特征点
  11. 什么是前后端分离技术?
  12. 码洞原创深度技术文章大全 —— 高端面试必备
  13. 营收超10亿元,又一家英特尔与小米投资的中国半导体企业即将上市
  14. java与c#哪个用得多_Java和c#哪个更值得学习?
  15. DenseBox: Unifying Landmark Localization with End to End Object Detection
  16. 书到用时方恨少? 整理了一份初中、高中数学教材pdf 百度云
  17. PS 不能使用移动工具 因为目标图层被隐藏怎么办
  18. Opencv环境的配置与基本使用
  19. 服务器能当电脑用吗?与普通电脑有何区别?
  20. 一篇文章让你搞懂Mysql InnoDB内存结构

热门文章

  1. H5分享页面(1)——web端二次分享配置内容
  2. java面试换背景颜色_正在修生养息,突然收到阿里(蚂蚁)面试电话,四面阿里面经总结...
  3. linux 用户 组区别吗,Linux用户组之主组和附加组
  4. ImportError: No module named urlgrabber.grabber
  5. 【windows】在控制面板卸载软件的时候,出现2502,2503的问题
  6. JMeter性能测试之使用CSV文件参数化
  7. Python爬虫【如何爬取内容(html)和解析内容】
  8. concat,ucase/lcase,left/right,length,replace
  9. 华硕ROG|玩家国度 魔霸7Plus G713PV win11原厂系统 带ASUS Recovery
  10. Djange构建招聘信息爬虫系统