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

简介: 【C++学习手札】一文带你认识C++虚继承​​
+关注继续查看

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

        什么是菱形继承?

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

    🌰

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;
 }

 内层结构 

        这段代码的内层结构如下:        

image

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

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


💮二、什么是虚继承?

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

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

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


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


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

语法定义

class Base {
  
};
 
class Derived : virtual public Base {
 
};

🌰

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:(未变,因为改变的不是他)

image

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

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

image

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

image

image

🌺三、使用虚继承的原因

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

一图让你明白~

image


🌼四、使用虚继承需注意

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

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



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

相关文章
|
8天前
|
算法 C++ Python
从入门到精通:C++ 学习路线指南,附详细学习计划
C++是一种高级编程语言,广泛用于开发操作系统、应用程序、游戏和各种工具。如果你想学习这门语言,以下是一个适合初学者的学习路线:
24 0
|
10天前
|
安全 C++
【C++】从认识using namespace std开始进入C++的学习
【C++】从认识using namespace std开始进入C++的学习
14 0
|
10天前
|
存储 安全 Java
【C++】引用之带你“消除”C语言版数据结构教材的一些困惑(虽然是C++的内容,但是强烈建议正在学习数据结构的同学点进来看看)
【C++】引用之带你“消除”C语言版数据结构教材的一些困惑(虽然是C++的内容,但是强烈建议正在学习数据结构的同学点进来看看)
25 0
|
10天前
|
人工智能 分布式计算 Java
【C++初阶】前言——C++的发展简述及学习方法分享
之前我们一直分享C语言和使用C语言完成数据结构的初阶的文章,今天我们正式进入C++的学习,这篇文章主要是给大家带来的是C++的由来、以及和C语言的区别、更主要的是和大家分享自己的学习方法,给一些我的建议。
|
20天前
|
C语言 C++
C++入门学习(3)函数重载
C++入门学习(3)函数重载
|
20天前
|
存储 安全 编译器
C++入门学习(4)引用 (讲解拿指针比较)
C++入门学习(4)引用 (讲解拿指针比较)
|
20天前
|
C语言 C++
C++入门学习(2)缺省参数
C++入门学习(2)缺省参数
|
20天前
|
编译器 C语言 C++
C++入门学习(1)命名空间和输入输出
C++入门学习(1)命名空间和输入输出
|
26天前
|
人工智能 物联网 编译器
【C++初阶(一)】学习前言 命名空间与IO流
【C++初阶(一)】学习前言 命名空间与IO流
29 0
|
1月前
|
存储 搜索推荐 Linux
5个值得学习的C++完整项目实战
5个值得学习的C++完整项目实战
相关产品
云迁移中心
推荐文章
更多