【C++学习手札】一文带你认识C++虚继承

食用指南:本文在有C++基础的情况下食用更佳

🍀本文前置知识:C++虚函数(很重要,内部剖析)

♈️++今日夜电波:++ 僕らのつづき---柊優花

1:06 ━━━━━━️💟──────── 3:51

🔄 ◀️ ⏸ ▶️ ☰

💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


目录

🌸一、虚继承的引入---菱形继承

什么是菱形继承?

🌰

内层结构

💮二、什么是虚继承?

语法定义

🌰

内层结构

🌺三、使用虚继承的原因

🌼四、使用虚继承需注意


🌸一、虚继承的引入---菱形继承

什么是菱形继承?

菱形继承是指在继承关系中存在一个派生类同时继承自两个或多个基类,而这些基类又共同继承自同一个基类。这样就会导致派生类中存在多个相同的基类子对象,从而造成资源浪费和二义性问题。

🌰

cpp 复制代码
class Animal
	 {
 public:
	 int data;
	 };

class Sheep :public Animal
	 {
 public:
	 };
 class Tuo :public Animal
 {
 public:
	 };

 class SheepTuo :public Sheep, public Tuo
 {
 public:
	 };
 int main(int argc, char* argv[])
 {
	 SheepTuo st;
	 //SheepTuo 从Sheep中继承data 从Tuo继承data 就产生二义性
	 //st.data = 200;//err
	 //第一种方式:加作用域解决
	 st.Sheep::data = 200;
	 st.Tuo::data = 300;
	
	 return 0;
 }

内层结构

这段代码的内层结构如下

这就是典型的菱形继承的例子,SheepTuo 从Sheep中继承data 从Tuo继承data 就产生二义性。但是我们可以采用加作用域的方式解决问题。

那有没有更加优的解决办法呢?答案是虚继承!


💮二、什么是虚继承?

++本文为虚函数后的知识, 强烈建议各位先去了解一下此文:++

🍀本文前置知识:C++虚函数(很重要,内部剖析)**

在多继承中,如果一个派生类从两个或多个基类继承,而这些基类又共同继承自同一个基类,那么就会出现菱形继承问题。这种情况下,派生类将会有两份相同的基类成员,导致二义性和冗余。

虚继承通过在派生类对共同基类的继承前**加上关键字"virtual"**来解决这个问题。使用虚继承后,共同基类的成员只会在派生类中存在一份,从而避免了二义性和冗余。

通过使用虚继承,可以确保多继承中的共同基类只会在派生类中存在一份,从而解决菱形继承问题。

语法定义

cpp 复制代码
class Base {
  
};

class Derived : virtual public Base {

};

🌰

cpp 复制代码
class Animal
	 {
 public:
	 int data;
	 };

class Sheep :virtual public Animal
	 {
 public:
	 };
 class Tuo :virtual public Animal
 {
 public:
	 };

 class SheepTuo :public Sheep, public Tuo
 {
 public:
	 };
 int main(int argc, char* argv[])
 {
	 SheepTuo st;
	 //在加入virtual后二义性以及冗余得以解决
	 st.data = 200;
	
	 return 0;
 }

内层结构

这段代码的内层结构如下

Animal: (未变,因为改变的不是他)

Sheep: (产生了虚基指针和虚基表)

Tuo: (同样也产生了虚基指针和虚基表)

SheepTuo:(保存了两个父类的虚基指针)


🌺三、使用虚继承的原因

敏锐的你可能已经发现了,每当使用了virtual以使用虚继承后,相对于没有使用虚继承的子类,他们的的内存都加了4字节的vptr指针,而最后的最后的那个子类则是多出了两个4字节的vptr指针,很明显,通过内层结构图我们得知,这两个指针分别指向这个子类的两个父类的虚基表vftable。之所以 产生 vbptr和vbtable目的 是为了保证 不管多少个继承 虚基类的数据只有一份。

一图让你明白~


🌼四、使用虚继承需注意

虚继承只有在多继承时才有用。虚继承只能解决具备公共祖先的多继承所带来的二义性问题,不能解决没有公共祖先的多继承的。单继承以及只有一层的继承都是不行的。

虚继承:不管继承多少次 虚基类 只有一份。


感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o!

给个三连再走嘛~

相关推荐
Want5951 分钟前
C/C++圣诞树①
c语言·开发语言·c++
老赵的博客12 分钟前
c++ 杂记
开发语言·c++
jimmy.hua15 分钟前
[C++刷怪笼]:set/map--优质且易操作的容器
开发语言·c++
tan180°27 分钟前
Boost搜索引擎 网络库与前端(4)
linux·网络·c++·搜索引擎
bkspiderx1 小时前
C++经典的数据结构与算法之经典算法思想:贪心算法(Greedy)
数据结构·c++·算法·贪心算法
w2sfot1 小时前
Passing Arguments as an Object in JavaScript
开发语言·javascript·ecmascript
郝学胜-神的一滴2 小时前
避免使用非const全局变量:C++中的最佳实践 (C++ Core Guidelines)
开发语言·c++·程序人生
搞一搞汽车电子2 小时前
S32K3平台eMIOS 应用说明
开发语言·驱动开发·笔记·单片机·嵌入式硬件·汽车
总有刁民想爱朕ha2 小时前
车牌模拟生成器:Python3.8+Opencv代码实现与商业应用前景(C#、python 开发包SDK)
开发语言·python·数据挖掘
小菜全3 小时前
uniapp新增页面及跳转配置方法
开发语言·前端·javascript·vue.js·前端框架