菱形继承二义性解决方法--虚拟继承

//虚拟继承是为了解决多重继承而出现的,比如
/*
			A
		   / \
          B   C
	       \ /
		    D
如果直接
class A{};
class B : public A{}
class C : public A{}
class D : public B, public C{}
那么在创建D的对象时候,将会生成2个A对象,1个B对象,1个C对象

如果采用虚拟继承
class A{};
class B : public virtual A{}
class C : public virtual A{}
class D : public B, public C{}
那么在创建D的对象时候,将会生成2个A对象,1个B对象,1个C对象
			
测试代码如下
*/
#include <iostream>
using namespace std;

class A
{
public:
	A(){cout << "A constructor"<<endl;}
	int a;
};
class B : public A
{
public:
	B(){cout << "B constructor"<<endl;}
};
class C : public A
{
public:
	C(){cout << "C constructor"<<endl;}
};
class D : public B,public C
{
public:
	D(){cout << "D constructor"<<endl;}
};

class B1 : public virtual A
{
public:
	B1(){cout << "B1 constructor"<<endl;}
};
class C1 : public virtual A
{
public:
	C1(){cout << "C1 constructor"<<endl;}
};
class D1 : public B1,public C1
{
public:
	D1(){cout << "D1 constructor"<<endl;}
};
int main()
{
	/*
	输出 A  B  A  C  D
	这样的话就又两个A,就会出现2义性,比如
	D d;
	d.B::a = 2;
	d.C::a = 3;
	是两个不同的a
	*/
	D d;

	
	size_t d_size = sizeof d;		//1
	
	D1 d1;
	size_t d1_size = sizeof d1;		//8,两个vpointer指向B和C的vtable
	/*
	输出 A  B1 C1  D1
	*/
	return 1;
}

普通继承内存分布


使用虚拟继承的内存分布


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
菱形继承(Diamond Inheritance)是指在一个继承体系中,派生类同时继承了两个直接或间接基类,而这两个基类又共同继承自同一个基类,形成了一个菱形的继承结构。在菱形继承中,派生类会间接地拥有两个相同的基类实例,这就导致了存储二义性问题。 存储二义性问题指的是派生类中的成员变量在内存中存在两份相同的拷贝,分别来自于两个共同的基类。这样就会造成以下问题: 1. 内存浪费:派生类实际上存储了两份相同的数据,占用了多余的内存空间。 2. 二义性访问:当访问派生类中的成员变量时,由于存在两份相同的拷贝,不明确应该访问哪一个。 考虑以下示例代码: ```cpp class Base { public: int data; }; class Derived1 : public Base { }; class Derived2 : public Base { }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond d; d.Derived1::data = 1; // 指定访问 Derived1 中的 data d.Derived2::data = 2; // 指定访问 Derived2 中的 data // d.data = ?; // 存储二义性,无法确定访问哪个基类中的 data return 0; } ``` 在上述代码中,Diamond 类通过多重继承同时继承了 Derived1 和 Derived2 两个基类,而这两个基类又都继承自 Base 基类。由于 Diamond 类间接地拥有了两份 Base 类的实例,当访问 Diamond 类的成员变量 data 时,就无法确定是访问 Derived1 中的 data 还是 Derived2 中的 data,导致了存储二义性问题。 为了解决存储二义性问题,可以使用虚拟继承(Virtual Inheritance)。通过在继承链中的共同基类前添加关键字 `virtual`,可以确保在继承链中只有一个共享的基类实例,从而消除了存储二义性问题。 总结起来,菱形继承中的存储二义性问题指的是派生类中的成员变量在内存中存在两份相同的拷贝,导致内存浪费和二义性访问的问题。使用虚拟继承可以解决这个问题,确保只有一个共享的基类实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值