继承机制中的二义性分为:同名二义性和路径二义性。以下用两个图解释两种二义性的区别和解决方法:
或(图画的丑不要介意)
如图1:
D d;
d.x;此时d.x指的是C的x还是D的x,即出现了同名二义性。
如图2:
D d;
d.x;此时指的是B的x还是C的x,即出现了同名二义性。
解决方法一:用类名来限定d.C::x或d.B::x
解决方法二:同名覆盖
图3
如图三:
D d;
d.x;此时d.x指的是A的x还是D的x,即出现了路径二义性。
解决方法:
引入虚基类(用于有共同基类的多继承场合(多层共祖))
Class A
class B : virtual public A
class C : virtualpublic A
class D: public B, public C
在子类对象中,最远基类成分是唯一的。于是下面的访问是正确的:
D d;
d.x;//d可以调用最远基类的成员
/*实验题目1:多继承二义性的验证
(1)程序功能简介
设计一个完整程序验证多继承机制中的二义性问题。
(2)程序设计说明
① 对于多继承机制中的同名二义性,分别定义三个类:A、B和C。其中,类C分别从类A和类B公有继承而来。
在类A和类B的public区域中分别具有相同的数据成员x和成员函数showx(),类C中没有数据成员x和成员函数showx(),
则由类C创建的一个对象c在使用数据成员x和成员函数showx()时会产生同名二义性;
② 对于多继承机制中的路径二义性,分别定义四个类:A、B、C和D。其中,类B和类C均从类A公有继承而来,类D从类
B和类C公有继承而来。在类A的public区域中具有数据成员x和成员函数showx(),类B、C、D中没有数据成员x和成员函数
showx(),则由类D创建的一个对象d在使用数据成员x和成员函数showx()时会产生路径二义性;
③ 为上述类分别添加合适的构造函数,实现类的各自数据成员的初始化,并分别修改代码解决上述两种二义性;
④ 编写完整的程序并测试。*/
#include<iostream.h>
class A
{
public:
int x;
A()
{
x=1;
}
void showx()
{
cout<<x<<endl;
}
};
//同名二义性
/*class B
{
public:
int x;
showx()
{
x=2;
cout<<x<<endl;
}
};
class C:public A,public B
{
};*/
//路径二义性
class B:public A
{
};
class C:public A
{
};
class D:public B,public C
{
public:
int x;
D()
{
x=4;
}
void showx()
{
cout<<x<<endl;
}
};
void main()
{
/*C test;
test.A::showx();
test.B::showx();*/
D test2;
test2.showx();//直接输出,输出的是D中的成员函数
test2.B::showx();//输出A中成员函数
}