c++菱形继承与虚继承

菱形继承:如有一基类动物类,该基类有俩个派生类🐏类和驼类。然后羊驼类有继承了🐏类和驼类,这四者的继承关系图形构成了一个菱形。代码如下所示

# 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 test01() {
	SheepTuo st;
	st.sheep :: age = 18;
	st.Tuo::age = 28;
	//当出现菱形继承时,出现属性冲突时,需要加以说明
	//cout << "羊驼的年龄:" << st.age << endl;
}
int main() {
	test01();

}

  

此时出现一个问题,羊驼本身年龄只要一份就行。但现在有俩份,怎样解决那,此时就用到了虚继承:代码如下
# 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 test01() {
	SheepTuo st;
	st.sheep :: age = 18;
	st.Tuo::age = 28;
	//当出现菱形继承时,出现属性冲突时,需要加以说明
	//此时出现一个问题,羊驼本身年龄只要一份就行
	//但现在有俩份,怎样解决那,方法:利用虚继承可以解决
	//在继承之前加上virtual关键字
	//虚继承原理一定要知道
	cout << "羊驼的年龄:" << st.age << endl;
}
int main() {
	test01();

}

  这时就可以解决之前菱形继承所带来的问题了。

显然,虚继承之所以能够实现在多重派生子类中只保存一份共有基类的拷贝,关键在于vbptr指针。那vbptr到底指的是什么?又是如何实现虚继承的呢?下面的类SheepTuo内存布局图中已经给出答案:                                                             

实际上,vbptr指的是虚基类表指针(virtual base table pointer),该指针指向了一个虚表(virtual table),虚表中记录了vbptr与本类的偏移地址;第二项是vbptr到共有基类元素之间的偏移量。在这个例子中,类sheep中的vbptr指向了虚表S::$vbtable@sheep@,虚表表明公共基类sheep的成员变量age距离类SheepTuo开始处的位移为8,这样就找到了成员变量age,而虚继承也不用像普通多继承那样维持着公共基类的两份同样的拷贝,节省了存储空间。



posted @ 2020-06-17 21:50  jhw-  阅读(321)  评论(0)    收藏  举报