感触:在学习一项内容的时候,我们首先应该对要学习的内容进行详细划分,然后循序渐进的学习划分出来的要点。这样学习起来才会有条理。
什么是虚基类?为什么叫虚基类?
class A{};
class B : virtual public A {};
此时,称class A为class B的虚基类。虚基类主要是为了和普通的基类相区别,在正常情况下,继承之后,我们说子类中有一个完整的父类对象。但是通过虚继承,编译器就会把基类中重复的内容去除掉,只保留第一个虚基类中的重复部分。
虚继承下的内存结构模型:
示例代码:
为了比较,我们先列出普通继承下的一些内容,
class A
{
public:
inta;
A()
{
a= 3;
}
voidfunc()
{
printf("AAAA");
}
};
class B : public A // 继承语句 mark
{
public :
B()
{
a= 5;
b= 7;
}
voidfunc()
{
printf("BBBB");
}
inta;
intb;
};
int _tmain(int argc,_TCHAR* argv[])
{
B*pb = new B();
pb->func();
return0;
}
这里面包含一些我们之前说过的成员覆盖问题。
观察内存,B对象的内存空间如下 (B占 12个字节)
覆盖情况下,继承来的成员仍然是分配空间的。只不过编译器限制我们对他进行使用。
虚继承示例:
我们把上面代码的mark 处改为
class B :virtual public A
执行之后,观察内存空间。
首先 ,对象的前4个字节,保存了一个地址,00D7D994, 它是代码段的一个地址,但目前里面都是一些无意义 的指令,具体作用我们在多态里面详细说明。然后是B添加的两个成员,最后才是从A虚继承来的。
考虑一个问题,添加这个语句 A * pa = pb; 那么 pa == pb?
答案是否定的,虚继承的情况下,pa的值位最后虚继承来的A对象的的首地址,而pb 是B对象的首地址。
关于这部分内容可以不必深入了解,只要掌握常规用法即可。实际使用的情况并不多。