C++中常见的两种二义性问题及其解决方式
--------------------------------一、“倒三角”二义性问题-------------------------------
问题描述:卤煮之所以称之为“倒三角问题”,是因为这一类二义性问题所处的继承体系类似于倒三角形状,如图:
这样,在子类中就存在父类A、B的两份show(),在调用的时候就会出现二义性问题,这种问题该怎么解决呢?
/*
class grandpa
{
public:
void show()
{
cout<<"This is grandpa\n";
}
};
class father
{
public:
void show()
{
cout<<"This is father\n";
}
};
class son:virtual public grandpa,virtual public father
{
public:
void display()
{
cout<<"This is son\n";
}
};
int main()
{
son son;
son.show();
son.display();
cout << "Hello world!" << endl;
return 0;
}
//这里的“倒三角”问题二义性怎么解决?即有两个基类共同派生出一个子类,这两个基类中又同时存在相同的功能的时候
//派生出的子类在调用该功能的时候也会出现二义性问题 这时候该怎么解决?
//解决方法:利用区域限定符(::) 详细解决方案见实验tempt
using namespace std;
//下面这种情况出现的二义性怎么解决?
class grandpa
{
public:
void show()
{
cout<<"This is grandpa\n";
}
};
class father
{
public:
void show()
{
cout<<"This is father\n";
}
};
class son:virtual public grandpa,virtual public father
{
public:
void display()
{
cout<<"This is son\n";
}
};
int main()
{
son son;
son.father::show();//“倒三角”问题出现的二义性利用区域限定符(::)来解决
son.grandpa::show();
son.display();
return 0;
描述:有最基类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,就导致了二义性。
解决方案: 虚基类、虚继承
教科书上面对C++虚基类的描述玄而又玄,名曰“共享继承”,名曰“各派生类的对象共享基类的的一个拷贝”,其实说白了就是解决多重多级继承造成的二义性问题。例如有基类B,从B派生出C和D,然后类F又同时继承了C和D,现在类F的一个对象里面包含了两个基类B的对象,如果F访问自己的从基类B那里继承过来的的数据成员或者函数成员那么编译器就不知道你指的到底是从C那里继承过来的B对象呢还是从D那里继承过来的B对象。
于是虚基类诞生了,将C和D的继承方式改为虚继承,那么F访问自己从B那里继承过来的成员就不会有二义性问题了,也就是将F对象里的B对象统一为一个,只有一个基类B对象,下面是一段代码说明了对虚基类的使用。
#include <iostream>
using namespace std;
class A
{
public:
int i;
void showa(){cout<<"i="<<i<<endl;}
};
class B:virtual public A //此处采用虚继承
{
public:
int j;
};
class C:virtual public A //此处采用虚继承
{
public:
int k;
};
class D:public B,public C
{
public:
int m;
};
int main()
{
A a;
B b;
C c;
a.i=1;
a.showa();
b.i=2;
b.showa();
c.i=3;
c.showa();
D d;
d.i=4;
d.showa();
//cout << "Hello world!" << endl;
return 0;
}
从这个代码我们可以看出B,C,D从A那里继承过来了i这个变量并且它们之间不会有任何影响,如果B和C不是虚继承方式的,那么d.i=4;就不能编译通过了。
最新文章
- 从头开始搭建分布式日志平台的docker环境
- 根据职位名,自动生成jd
- java 中byte[] 数组的合并
- 12.1 文档相关 Webbrowser 该文档已被修改,是否保存修改结果
- Android 设置按钮为透明
- C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)
- Effective JavaScript :第一章
- C#在win10(win8)下读写记事本注意事项
- Python——plot可视化数据,作业8(python programming)
- Docker命令详解(run篇)
- Java匹马行天下之JavaSE核心技术——面向对象
- RedisDump安装报错
- jquery评分效果Rating精华版
- idea创建maven项目报错,Error initializing: org.codehaus.plexus.velocity.DefaultVelocityComponent@56da52a7 java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils
- shell中十种实现自加的方法
- 剑指offer三从头到尾打印链表
- jenkins 使用Git持续构建
- Eclipse QuickSear的插件的说明
- 201621123018《Java程序设计》第3周学习报告
- Python 爬虫之模拟登录
热门文章
- bzoj1588
- 运行tomcat8w.exe未安装指定的服务
- Windows 10一周年更新正式版官方ISO镜像(1607)
- bzoj 4553 &;&; HEOI2016 day1t3 seq
- 11月14日用AJAX、PHP、SESSION做购物车
- postgresql利用pg_upgrade升级数据库(从8.4升级到9.5)
- linux /proc/meminfo 文件分析(转载)
- Linux Socket编程
- (PPT)Linux服务器基础
- Linux tar (打包.压缩.解压缩)命令说明 | tar如何解压文件到指定的目录?