IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++虚拟继承那些事 -> 正文阅读

[C++知识库]c++虚拟继承那些事

[@toc]
class

在c++中,会遇到菱形继承的情况。

内存情况

c++内存模型告诉我们,当我们创建一个派生类对象B时,同时会创建一个父类的A对象。
对于上面的这种菱形模型, B C 都创建时,都会创建一个A,所以会有两个A。这是造成了内存上的浪费。

测试代码如下:

#include <iostream>
using namespace std;

class A
{
    public:
    A()
    {
        cout << "  A ctor \n";
    }
};

class B: public A
{
    public:
    B()
    {
        cout << "   B ctor \n" ; 
    }
};

class C : public A
{
    public:
    C()
    {
        cout << "   C ctor  \n";
    }
};

class D : public B,C
{
    public:
    D()
    {
        cout << "   D ctor  \n";
    }
};

int main()
{
    D d;
}

输出代码是

A ctor 
   B ctor 
  A ctor 
   C ctor  
   D ctor 

可以看出,A对象被创建了两次。

虚拟继承

为了解决这个问题,c++引入了虚拟继承,即 BC virtual 继承A
代码如下

#include <iostream>
using namespace std;

class A
{
    public:
    A()
    {
        cout << "  A ctor \n";
    }
};

class B: virtual public A
{
    public:
    B()
    {
        cout << "   B ctor \n" ; 
    }
};

class C : virtual public A
{
    public:
    C()
    {
        cout << "   C ctor  \n";
    }
};

class D : public B,C
{
    public:
    D()
    {
        cout << "   D ctor  \n";
    }
};

int main()
{
    D d;
}

这种情况下的输入情况是

  A ctor 
   B ctor 
   C ctor  
   D ctor 

可以看到A 只被构建了一次。

这就完了吗? 当然不是,接下来分析更复杂的情况,比如

  • A是在哪里被构建的?
  • A 如果带参数会是怎么样的?

在这里插入图片描述
发个广告 2023 应届生招聘,学历要求 985硕士,我可以帮忙内推
招聘

原理分析

A 在哪里构建?

在B C D的视角中,A的constructor 我们称为virtual base class constructor。对于他的初始化,有这么个规律 只有当一个完成的class object被定义出来时,它才会被调用。如果object只是某个完整object的subobject,那么他不会被调用
在这里,当我们初始化D时,B,C都是subobject,所以他们的构造函数都无法触发A的构建。开始构建D时,才会触发A的构建。
因此,A是在D 开始构建时构建的。

在书中,我们看到维持这个机制的做法是,在 BC 的构造函数中设置一个检查flag,只有当flag为true时,才会构建A。

B b;

这种情况,flag是有B设置,为true. A 会被构建出来。

D d;

这种情况,在D的构造函数中,D会把flag设为false,然后构建B。 B也就无法构建A了。

具体参考 深度探索c++ 第五章 构造析构拷贝语义 , 代码就不贴了。

有参数情形

如下案例代码

#include <iostream>
using namespace std;

class A
{
    public:
    A()
    {
        cout << "A ctor none  \n"  << endl;
    }
    A(int x1): x(x1)
    {
       cout <<"A ctor x :" << x <<endl; 
    }

    virtual void hello()
    {
    }

    int x;
};

class B : virtual public  A
{
    public:

    B(int x1, int y1):A(x1),y(y1)
    {
        cout << " B ctor y: " << y << endl;
    }

    int y;
};

class C :  virtual public A
{
    public:

    C(int x1, int y1):A(x1),y(y1)
    {
        cout << " C ctor y: " << y << endl;
    }

    int y;
};

class D: public B, public C
{
    public:
    
    // scenario1
    D(int x, int y) : B(x,y), C(x,y)
    {
        cout <<" D  x y :" << x << "  " << y << endl;
    }
    
   // scenario 2
 //D(int x, int y) : B(x,y), C(x,y), A(x)
 //  {
 //    cout <<" D  x y :" << x << "  " << y << endl;
 //  }
};


int main()
{
    D c(1,10);  // 
    return 1;
}

主要观察D 的两种构造函数,如果是scenario1, 虽然B C 中使用了 A(x)的构造函数,但是并不是真正的被调用。原因是BC此时是subobject,不会触发A的构建。因此会A()会被触发。
scenario2, 此时A(x)会被触发。

输出结果是:
scenario1:

A ctor none  

 B ctor y: 10
 C ctor y: 10
 D  x y :1  10

scenario2

A ctor x :1
 B ctor y: 10
 C ctor y: 10
 D  x y :1  10
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 10:54:41  更:2022-09-13 10:57:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 14:06:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码