C++ 多态之虚继承

什么是虚继承?

C++支持多继承的形式,但若被继承的不同基类又同属与某一个接口类or基类的派生类,那么很容易产生经典的菱形继承问题,这样不可避免的带来了命名冲突,访问不明确的问题,如图所示:
在这里插入图片描述

虚继承解决的问题菱形继承是什么?
  1. 基类A派生出类B和类C
  2. 派生类D同时继承自类B和类C,这时候基类A中的成员变量、成员函数在类D中变成了两份
  3. 路径1:A–>B–>D;路径2:A–>C–>D

派生类中保留间接基类的多份成员,保留的成员分别存储在不同的直接基类下,虽然可以通过类+作用域的形式去访问修改,但这很容易产生bug,大多数情况下都是冗余的。

代码释义及原理分析
//base基类A
class A {
protected:
	int m_a;
};
//派生基类B
class B : public A {
protected:
	int m_b;
};
//派生基类C
class C : public A {
protected:
	int m_c;
};
//派生类D
class D : public B, public C {
public:
	void Set_a(int a) { 
		m_a    = a; //访问不明确
		C::m_a = a; //C中的a
		B::m_a = a;  //B 中的a
	}
private:
	int m_d;
};

这个问题在编译期就会报错,告知访问不明确,从D的内存布局上们也可以清楚的看到m_a变量会有两份,分别在Base Class B和Base Class C下面

在这里插入图片描述

虚继承
//base基类A
class A {
protected:
	int m_a;
};
//派生基类B
class B : virtual public A {
protected:
	int m_b;
};
//派生基类C
class C : virtual public A {
protected:
	int m_c;
};
//派生类D
class D : public B, public C {
public:
	void Set_a(int a) { 
		m_a    = a; //虚基类中的a
		C::m_a = a; //虚基类中的a
		B::m_a = a; //虚基类中的a
	}
private:
	int m_d;
};

只需要我们基类B和C的定义时,通过virtual public A 的方式进行虚继承,这样在内存布局上,类B或者C的内存布局就会添加一个虚基类指针,并指向虚基类表。
在这里插入图片描述

另外我们也可以通过编译器直接查看内存布局,发现和我们的分析完全一致,这样当我们需要访问m_a时都会最终通过虚基类表,找到唯一的一份变量。
在这里插入图片描述

虚继承的常见问题
  • 间接基类没有虚继承,直接基类进行虚继承,最终仍会保留多份间接基类
    在这里插入图片描述

  • 一个直接基类通过虚继承派生,另一个直接基类普通继承,也会保留两份间接基类,一份在直接继承的类中,另一份在虚基类中
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值