导言
在派生类中对基类成员访问应该是唯一的,但是在多继承时,可能会导致对基类某成员访问出现不一致的情况,这就是C++多继承中的二义性。
出现二义性主要有以下两种情况
情况一:
如果一个派生类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的成员变量进行访问时,可能产生二义性,继承关系如下图所示:
另外我们可以通道实例证明:
#include <iostream>
using namespace std;
class A{
public:
int a;
};
class B1 : public A{
public:
int b1;
};
class B2 : public A{
public:
int b2;
};
class C : public B1, public B2{
public:
int c1;
};
int main(){
C c1;
c1.b1 = 100;
c1.b2 = 200;
c1.c1 = 300;
c1.a = 500; //继承的二义性 和 虚继承解决方案
cout << "end..." << endl;
system("pause");
return 0;
}
编译时提示:
我们可以看到,编译器说a是模糊不清。
那么通过什么方法可以解决呢,答案是虚继承,即在B1和B2继承A时加上virtual关键字即可,如下所示:
#include <iostream>
using namespace std;
class A{
public:
int a;
};
class B1 : virtual public A{
public:
int b1;
};
class B2 : virtual public A{
public:
int b2;
};
class C : public B1, public B2{
public:
int c1;
};
int main(){
C c1;
c1.b1 = 100;
c1.b2 = 200;
c1.c1 = 300;
c1.a = 500; //继承的二义性 和 虚继承解决方案
cout << "end..." << endl;
system("pause");
return 0;
}
情况一有以下问题:
1. 那么问题来了,B1和B2加virtual关键字与否他们的类大小是否相等,答案是不相等的,继承时加了virtual关键字类的空间会大四个字节,也就是会加入一些特性来解决C++多继承的二义性。
2. B1和B2没有共同的基类,但是他们有同名的成员,而C继承了B1和B2同时加入virtual关键字能否解决多继承二义性问题?测试发现是不能解决的,详见以下“情况二”。
情况二:
派生类在访问基类成员时,由于基类存在同名的成员,基类不知道是方法谁
#include<iostream>
using namespace std;
class Base1 {
public:
void fun() {
cout << "I am base-1 " << endl;
};
};
class Base2
{
public:
void fun() {
cout << "I am base-2 " << endl;
};
};
class Subclass : public Base1, public Base2 {
public:
void print() {
}
};
int main() {
Subclass obj;
obj.fun(); //产生二歧义
system("pause");
return 0;
}
同样产生二义性结果:
这个问题可以在访问基类成员时使用作用域运算符来解决,即obj.Base1::fun()方式,如上例写成:
obj.Base1::fun();