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

内层结构

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

       这就是典型的菱形继承的例子,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:(未变,因为改变的不是他)

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

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

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

🌺三、使用虚继承的原因

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

一图让你明白~


🌼四、使用虚继承需注意

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

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



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

相关文章
|
1月前
|
Java 编译器 程序员
C++中的语法知识虚继承和虚基类
**C++中的多继承可能导致命名冲突和数据冗余,尤其在菱形继承中。为解决这一问题,C++引入了虚继承(virtual inheritance),确保派生类只保留虚基类的一份实例,消除二义性。虚继承通过`virtual`关键字指定,允许明确访问特定路径上的成员,如`B::m_a`或`C::m_a`。这样,即使基类在继承链中多次出现,也只有一份成员副本,简化了内存布局并避免冲突。虚继承应在需要时提前在继承声明中指定,影响到从虚基类派生的所有后代类。**
43 7
|
1月前
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
1月前
|
人工智能 分布式计算 Java
【C++入门 一 】学习C++背景、开启C++奇妙之旅
【C++入门 一 】学习C++背景、开启C++奇妙之旅
|
1月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
|
1月前
|
小程序 C++
【C++入门 二 】学习使用C++命名空间及其展开
【C++入门 二 】学习使用C++命名空间及其展开
|
1月前
|
存储 C++ 索引
|
1月前
|
存储 C++ 容器
|
1月前
|
C++
C++基础知识(四:类的学习)
类指的就是对同一类对象,把所有的属性都封装起来,你也可以把类看成一个高级版的结构体。
|
1月前
|
算法 C++ 容器