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 c;
};
int main()
{
C c1;
c1.a=5;
return 0;
}
上面代码是一个简单的菱形继承代码,具有编译错误。
顶层的A公有派生子类B1,B2;
而底层的C类共有继承于B1,B2;
那么就产生于一个问题:
就是创建一个c类对象,通过c类对象访问变量a
编译器不知道是访问B1类的继承下来的B1::a,还是B2::a。
这就是菱形继承的二义性问题。
这个问题可以有两个解法。
第一个也是最不提倡的解法,就是在通过c对象访问a变量时注明是访问哪一个继承对象的变量。
代码如下:
#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 c;
};
int main()
{
C c1;
c1.B1::a=5;//访问B1中的a变量
return 0;
}
这种方法浪费了大量的空间,若顶层类的变量很多,则派生出的B1,B2类重复定义A类的变量很多,浪费很大。
以下我推荐第二种方法
即虚拟继承:代码如下
#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 c;
};
int main()
{
C c1;
c1.a=5;
return 0;
}
在A派生B1,B2类时,使用虚拟继承,
这样不仅解决了编译器的二义性问题,还会对空间进行节省,
使用虚拟继承为什么会节省空间呢。
因为在使用虚拟继承时,B1和B2在定义时不会按照传统的类模型,而是在后面创建一个空间来储存A类变量,B1和B2中有指针可以找到这个空间,这样就节省了空间。后面A类变量空间是B1和B2共有的。