首先要说一下多继承,虚基类和虚继承都是在多继承的一种情况下存在的内容。
多继承是子类继承自多个父类的继承方式。
但是在多继承的过程中,存在这样一种情况,一个基类A分别被中间基类B、C继承,然后D又继承了B、C,此时就出现了问题
?如果子类D使用父类B或者父类C独有的成员变量,这时没有问题。但是如果D使用的是A的成员变量,编译器就不知道使用的B继承自A的还是C继承自A的,产生了一个语义模糊的概念(aimbiguous的错误)。
注:成员函数是可以被多继承的而不产生上述问题,因为函数是在编译阶段就已经生成了内存的,不需要像成员变量一样之后还会有更改。
这时候,就一定要引入虚继承的概念来避语义的模糊,让B、C类虚继承自A,那么A的成员变量在D中只会保留一份,所以取消了语义模糊冲突(具体在内存中为什么会这样我还得在思考思考)。
意味着虚继承是一种简介继承的模式,对虚继承的子类本身没有问题,只对该子类的子孙(具体是再往下继承一层还是多层需要实验)有影响。
#include <iostream>
using namespace std;
class A {
protected:
int A_a;
};
class B : public A {
protected:
int B_b;
};
class C : public A {
protected:
int C_c;
};
class D : public B, public C {
protected:
int D_d;
public:
// 此时就出现了问题,编译器不知道调用的a是继承自B的还是继承自C的,所以会产生模棱两可的情况即ambiguous,此时就要引出超级无敌的虚继承!!!
//void A_func () {A_a = 1;}
void B_func () {B_b = 2;}
void C_func () {C_c = 3;}
void D_func () {D_d = 4;}
};
class I {
protected:
int i;
public:
void setI (int i) {
this->i = i;
}
int retI () {
return i;
}
void specialA () {
cout << "funcA " << endl;
}
};
class J : virtual public I {
protected:
int j;
public:
void setI (int i) {
this->i = i;
}
int retI () {
return i;
}
};
class K : virtual public I {
protected:
int k;
public:
int retI () {
return i;
}
};
class H : public J, public K {
protected:
int H;
public:
void funcA () {i = 1;}
void funcB () {j = 2;}
void funcC () {k = 3;}
void funcD () {H = 4;}
const void SetI (int i) {this->i = i;}
const int retI () {return i;}
};
int main ()
{
// 在菱形继承&虚继承中,如果一个中间类改变了虚基类中的一个成员变量继承下来的值,那么这个虚基类的成员变量的值是否被改变呢,那么这个中间类的兄弟类的相同成员变量的值被改变了吗
I i;
J j;
K k;
H h;
cout << "I: " << i.retI () << endl;
cout << "J: " << j.retI () << endl;
cout << "K: " << k.retI () << endl;
cout << "H: " << h.retI () << endl;
cout << "可以看到此时所有的I都是未初始化的状态,但是所指向的内存却不同" << endl;
i.setI (1);
cout << "将I中的i设置为1之后:" << endl;
cout << "I: " << i.retI () << endl;
cout << "J: " << j.retI () << endl;
cout << "K: " << k.retI () << endl;
cout << "H: " << h.retI () << endl;
j.setI (2);
cout << "将J中的i设置为2之后:" << endl;
cout << "I: " << i.retI () << endl;
cout << "J: " << j.retI () << endl;
cout << "K: " << k.retI () << endl;
cout << "H: " << h.retI () << endl;
k.setI (3);
cout << "将K中的i设置为3之后:" << endl;
cout << "I: " << i.retI () << endl;
cout << "J: " << j.retI () << endl;
cout << "K: " << k.retI () << endl;
cout << "H: " << h.retI () << endl;
h.setI (4);
cout << "将H中的i设置为4之后:" << endl;
cout << "I: " << i.retI () << endl;
cout << "J: " << j.retI () << endl;
cout << "K: " << k.retI () << endl;
cout << "H: " << h.retI () << endl;
h.specialA ();
// 由此可见,虚继承中不同的类并不是共享内存的,应该是在类似于虚函数表的地方表示虚继承前后的变量
return 0;
}
ps:问题?1.虚继承在一开始出现的时候就是为了解决上述问题的吗?
2.虚继承只能用来解决这一个问题吗,还可以应用在哪些场景呢?