菱形继承的问题
菱形继承问题出现在多个子类继承父类的时候,将父类的数据一分为二,问题是在子类又出现了多继承的问题。被一分为二的属性又重新被赋值给了一个子类,本应该就是一份数据,这时确出现了两份,见如下案例
#include <iostream>
using namespace std;
class Animal
{
public:
int Age;
};
class Sheep : public Animal
{
};
class Tuo : public Animal
{
};
class SheepTuo : public Sheep, public Tuo
{
};
void text01(void)
{
SheepTuo st;
st.Sheep::Age = 18;
st.Tuo::Age = 28;
cout << "羊驼的年龄: " << st.Sheep::Age << endl;
cout << "羊驼的年龄: " << st.Tuo::Age << endl;
}
int main(void)
{
text01();
return 0;
}
解决办法
就是不让Age属性一分为二,问题出现在羊和驼继承父类的时候,将Age一分为二。 我们使用虚继承的方式,就可以避免将父类的属性一分为二 上代码
#include <iostream>
using namespace std;
class Animal
{
public:
int Age;
};
class Sheep : virtual public Animal
{
};
class Tuo : virtual public Animal
{
};
class SheepTuo : public Sheep, public Tuo
{
};
void text01(void)
{
SheepTuo st;
st.Sheep::Age = 18;
st.Tuo::Age = 28;
cout << "羊驼的年龄: " << st.Sheep::Age << endl;
cout << "羊驼的年龄: " << st.Tuo::Age << endl;
}
int main(void)
{
text01();
return 0;
}
c++开发人员命令提示工具
我们使用c++开发人员命令提示工具 跳转到当前的工程目录,可以用于查看c++的类内存布局
cl /d1 reportSingalClassLayoutSheepTuo main.cpp
首先分析一下第二种法情况
现在查看的是虚继承之后的情况
- 可以看到在Sheep和Tuo继承下来的东西叫vbptr,这个东西是虚基类指针的缩写virtual base ptr,这个指针指向的是vbtable(虚基类表的缩写 virtual base table)。Sheep类的虚基类指针指向的是Sheep的虚基类表,有上图可以看,这个表里记录的是虚基类指针的偏移量。所以Sheep类在原来0的位置加8就找到了Age的地址,同理Tuo类的偏移量是4,在原来的基础上加4也找到了Age 的地址。现在可以看出来为什么Age这份数据不会被一分为二了
第一种情况
在菱形继承问题中如果没有采用虚继承,我们在查看一下内存情况 由此可见未使用虚继承时,Age属性被拷贝了两份,继承的不再是指针。
|