C++:菱形继承与虚继承
看下面这个示例代码
class A{
public:
int num=10;
A(){cout<<"A构造"<<endl;}
virtual void fun(){cout<<"A虚函数"<<endl;}
};class B:public A{
public:
B(){cout<<"B构造"<<endl;}
void fun(){cout<<"B虚函数"<<endl;}
};class C:public A{
public:
C(){cout<<"C构造"<<endl;}
void fun(){cout<<"C虚函数"<<endl;}
};class D:public C,public B{
public:
D(){cout<<"D构造"<<endl;}
void fun(){cout<<"D虚函数"<<num<<endl;}
};
这段代码你会发现这段代码编译不通过,因为D类的虚函数在访问num时不知道访问哪个,将这个虚函数里面的内容清空然后执行会得到以下结果:

可以看到D多次继承了同一个基类,这样就造成了构造D时构造了多个A,问题本身没有什么影响但是如果D需要访问A中的东西时就会有两个渠道,通过B或者C,这时候加上作用域的话就可以运行了,但是这样太麻烦了,而且对共同的基类A真的没必要构造两次,为了处理这种情况引入了虚继承的概念。
之前介绍过虚函数,虚继承和它类似
- 发生虚继承的时候就会产生一个虚基表和相应的虚基表指针
- 虚基表是静态的,这点和虚函数表差不多
- 发生虚继承后对任意类只会创建一次
- 虚基表存储虚基表指针到其基类的偏移量
- 一个类只会有一个虚基表,但是可以有多个虚基表指针
这些概念后面梳理,现在先看修改后的代码
class A{
public:
int num=10;
A(){cout<<"A构造"<<endl;}
virtual void fun(){cout<<"A虚函数"<<endl;}
};
class B:virtual public A{
public:
B(){cout<<"B构造"<<endl;}
void fun(){cout<<"B虚函数"<<endl;}
};
class C:virtual public A{
public:
C(){cout<<"C构造"<<endl;}
void fun(){cout<<"C虚函数"<<endl;}
};
class D:virtual public C,virtual public B{
public:
D(){cout<<"D构造"<<endl;}
void fun(){cout<<"D虚函数"<<num<<endl;}
};
看看执行结果

可以看出问题被解决了,接下来看它在内存中的分布
在vs开发者命令行模式下输入下面的指令即可
cl /d1 reportSingleClassLayoutXXX 文件名.cpp
xxx替换为自己的类名,我这里是D

可以看到类的结构还是很清晰的,每个使用虚继承的类头部都有一个虚基表指针,同时虚函数表指针不再出现在头部,不需要过多解释自己看吧

虚继承通过减少基类的重复创建解决了多次继承同一基类造成的二义性问题,借助虚基表完成了基类的定位,可以说很是牛皮,但是缺点也很明显它破坏了类中的原有布局,它使类中的内存分布情况程序多样化,现在虚函数表指针可能有多个甚至位置也会按照继承的顺序而改变,内存的分布依赖于代码书写,所以说要慎用,虽然我们不需要过多关注内存,但是对性能的影响却是真实存在的。
相关文章:
C++:菱形继承与虚继承
看下面这个示例代码 class A{ public: int num10; A(){cout<<"A构造"<<endl;} virtual void fun(){cout<<"A虚函数"<<endl;} };class B:public A{ public: B(){cout<<"B构造"<<endl;} void fun(){cout<…...
贡献法:USACO 2021 December Contest Bronze:孤独的照片
Farmer John 最近购入了 N 头新的奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。 奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。 然而,他…...
Java实现简单的通讯录
每日一言 泪眼问花花不语,乱红飞过秋千去。 —欧阳修- 简单的通讯录实现,跟写Java实现图书管理系统差不多,用到的知识也差不多,就当个小练习,练习一下写Java程序的手感。 Java实现图书管理系统 关于通讯录的代码都写…...
服务器数据恢复—raid5热备盘上线同步数据失败的如何恢复数据
服务器数据恢复环境&故障&分析: 一台存储上有一组由多块硬盘组建的raid5阵列,该raid5阵列中的一块硬盘掉线,热备盘自动上线同步数据的过程中,raid阵列中又有一块硬盘掉线,热备盘的数据同步被中断,r…...
探索C语言中的循环结构
循环结构是程序设计中一种重要的控制结构,它允许程序重复执行特定的代码块,直到满足某个条件为止。在C语言中,循环结构有多种形式,如for循环、while循环和do-while循环。本文将介绍C语言中的循环结构,并讨论它们的用法…...
数学建模-估计出租车的总数
文章目录 1、随机抽取的号码在总体的排序 1、随机抽取的号码在总体的排序 10个号码从小到大重新排列 [ x 0 , x ] [x_0, x] [x0,x] 区间内全部整数值 ~ 总体 x 1 , x 2 , … , x 10 总体的一个样本 x_1, x_2, … , x_{10} ~ 总体的一个样本 x1,x2,…,x10 总体的一个样…...
设计模式在芯片验证中的应用——装饰器
一、装饰器模式 装饰器模式(Decorator)是一种结构化软件设计模式,它提供了一种通过向类对象添加行为来修改类对象的方法,而不会影响同一类的其它对象行为。该模式允许在不修改抽象类的情况下添加类功能。它从本质上允许基类代码对不可预见的修改具有前瞻…...
Python 查找并高亮PDF中的指定文本
在处理大量PDF文档时,有时我们需要快速找到特定的文本信息。本文将提供以下三个Python示例来帮助你在PDF文件中快速查找并高亮指定的文本。 查找并高亮PDF中所有的指定文本查找并高亮PDF某个区域内的指定文本使用正则表达式搜索指定文本并高亮 本文将用到国产第三方…...
LEETCODE LCS 03. 主题空间
题目描述如上,这个题主要运用了DFS的思想,同时走过的路径标记为6,即可在后续的遍历中过滤掉重复的元素,其他则类似边界条件的判断和题目条件的判断,求最大值,只需要一次遍历中累加对比每一次得即可。 模板&…...
【Spring Boot 源码学习】深入应用上下文初始化器实现
《Spring Boot 源码学习系列》 深入应用上下文初始化器实现 一、引言二、往期内容三、主要内容3.1 spring-boot 子模块中内置的实现类3.1.1 ConfigurationWarningsApplicationContextInitializer3.1.2 ContextIdApplicationContextInitializer3.1.3 DelegatingApplicationConte…...
【Docker】一文趣谈Docker
🏡浩泽学编程:个人主页 🔥 推荐专栏:《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 🛸学无止境,不骄不躁,知行合一 文章目录 …...
代码随想录day19(2)二叉树:二叉树的最大深度(leetcode104)
题目要求:求出二叉树的最大深度 思路:首先要区分二叉树的高度与深度。二叉树的高度是任一结点到叶子结点的距离,而二叉树的深度指的是任一节点到根节点的距离(从1开始)。所以求高度使用后序遍历(从下往上&…...
Lua中文语言编程源码-第五节,更改lcorolib.c协程库函数, 使Lua加载中文库关键词(与所有的基础库相关)
源码已经更新在CSDN的码库里: git clone https://gitcode.com/funsion/CLua.git 在src文件夹下的lcorolib.c协程库函数,Coroutine Library:表明这个C源文件实现了Lua的协程库(Coroutine Library),即提供了…...
Docker学习之数据管理(超详解析)
Docker存储资源类型: 用户在使用 Docker 的过程中,势必需要查看容器内应用产生的数据,或者需要将容器内数据进行备份,甚至多个容器之间进行数据共享,这必然会涉及到容器的数据管理: (1ÿ…...
FDTD液晶折射率各项异性表示方法
由于FDTD的数据都是沿坐标轴的,各向异性材料的参数也需要根据坐标轴来输入。 首先要了解坐标变换。 坐标变换 这里以二维坐标变化为例。 矢量下我们可以发现OP可在两个坐标系下分别表示 接下来将两个坐标相互关联,这里以Xb举例,Yb同理 注…...
RoketMQ主从搭建
vim /etc/hosts# IP与域名映射,端口看自己的#nameserver 192.168.126.132 rocketmq-nameserver1 192.168.126.133 rocketmq-nameserver2# 注意主从节点不在同一个主机上 #broker 192.168.126.132 rocketmq-master1 192.168.126.133 rocketmq-master2#broker 192.168…...
Linux网络瑞士军刀 nc(netcat)
1.命令简介 nc(netcat)是一个短小精悍、功能实用、简单可靠的网络工具,主要有如下作用: (1)端口侦听,nc 可以作为 server 以 TCP 或 UDP 方式侦听指定端口; (2&#x…...
1.Spring入门
1.1 Spring简介 Spring是一个轻量级Java 企业级应用程序开发框架,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。 Spring Fra…...
【JavaEE Spring 项目】消息队列的设计
消息队列的设计 一、消息队列的背景知识二、需求分析核心概念⼀个⽣产者, ⼀个消费者N 个⽣产者, N 个消费者Broker Server 中的相关概念核⼼ API交换机类型 (Exchange Type)持久化⽹络通信消息应答 三、 模块划分四、 项⽬创建五、创建核心类创建 Exchange创建 MSGQUeue创建 B…...
SpringFramework学习笔记(Spring IoC,aop,tx)
SpringFramework 本篇笔记是基于尚硅谷学习资料的整理,涉及到其笔记的简化,补充,以及我在学习中遇到的与无法理解的问题及解决,如果想看完整及后续的笔记,可以去https://www.wolai.com/v5Kuct5ZtPeVBk4NBUGBWF查看官方…...
C#编写CIP通讯源码——欧姆龙NX1P通讯DEMO
C#编写CIP通讯源码,欧姆龙NX1P通讯DEMO一、概述 本代码是基于C#语言开发的CIP(Common Industrial Protocol)通讯Demo程序,专门用于与欧姆龙NX1P2系列PLC进行工业通讯交互。程序采用.NET Framework 4.8框架开发,通过TCP…...
重构求职效率:boss_batch_push批量投递工具的颠覆性价值
重构求职效率:boss_batch_push批量投递工具的颠覆性价值 【免费下载链接】boss_batch_push Boss直聘批量投简历,解放双手 项目地址: https://gitcode.com/gh_mirrors/bo/boss_batch_push boss_batch_push是一款专为Boss直聘平台设计的开源自动化投…...
AIGlasses_for_navigation多场景落地:日常通勤、医院导诊、地铁站导航三场景实测
AIGlasses_for_navigation多场景落地:日常通勤、医院导诊、地铁站导航三场景实测 1. 引言:当导航从手机屏幕“走”到眼前 想象一下这样的场景:你走在陌生的城市街道,要去一个从未去过的咖啡馆。你不需要低头看手机地图ÿ…...
别再死记硬背了!用C++/Java手把手实现线索二叉树(附完整代码与避坑指南)
从零实现线索二叉树:C/Java双语言实战与陷阱全解析 第一次在面试白板上遇到线索二叉树的实现题时,我的手心全是汗。教科书上的递归图示看起来清晰,但真正要写出无bug的线索化代码时,那些ltag和rtag就像捉迷藏的孩子,总…...
三极管信号滤波原理与工程实践
1. 三极管在信号滤波中的独特应用作为一名嵌入式硬件工程师,我经常需要处理各种传感器信号。最近在无刷电机驱动项目中,遇到了霍尔信号毛刺干扰的问题。传统教科书上总是强调三极管的放大作用,但实际工程中,我发现三极管在信号滤波…...
C++ 智能指针的生命周期陷阱
C智能指针的生命周期陷阱:隐藏的坑与破解之道 在现代C开发中,智能指针作为资源管理的利器,极大减轻了开发者手动管理内存的负担。看似简单的shared_ptr、unique_ptr和weak_ptr背后,却隐藏着微妙的生命周期陷阱。这些陷阱可能导致…...
Topgrade性能优化技巧:提升大规模更新效率的5种方法
Topgrade性能优化技巧:提升大规模更新效率的5种方法 【免费下载链接】topgrade Upgrade all the things 项目地址: https://gitcode.com/gh_mirrors/top/topgrade Topgrade是一款强大的系统更新工具,它能自动检测并升级系统中的所有包管理器、编程…...
DBShadow横空出世,Dapper.net的天花板盖不住了
一、DBShadow是什么DBShadow是.net开源的高性能ORMDBShadow使用开源项目ShadowSql高效拼接sqlDBShadow使用开源项目PocoEmit.Mapper高效映射查询参数和查询结果也就是说SqlBuilder(ShadowSql)OOM(PocoEmit.Mapper)ORM(DBShadow)二、DBShadow和Dapper对比一下1. Dapper代码await…...
【实战】CodeBuddy使用技巧:5个Skills让编程效率翻倍的隐藏操作
目录摘要一、CodeBuddy不只是代码补全1.1 三种形态,覆盖全开发场景1.2 核心差异化二、Craft模式:一句话从0到上线2.1 实测案例:20分钟出一个完整MVP2.2 多模型切换策略2.3 Figma设计稿一键转代码三、5个效率翻倍的独有技巧3.1 技巧1ÿ…...
新手零障碍入门:在免激活的快马平台完成你的第一个Python小游戏
作为一个刚接触编程的新手,我最近在InsCode(快马)平台上完成了人生第一个Python小游戏——猜数字。整个过程比想象中简单得多,特别适合像我这样零基础的小白入门。下面分享我的学习笔记,希望能帮到同样想尝试编程的朋友。 为什么选择猜数字游…...
