当前位置: 首页 > news >正文

c++的虚继承说明、案例、代码

  1. 虚继承的基本概念

    • 在 C++ 中,虚继承主要用于解决多继承时可能出现的菱形继承问题。菱形继承是指一个类有两个(或更多)子类,而这两个子类又同时继承自一个共同的基类,当这些子类又被另一个类继承时,就形成了菱形结构。在这种情况下,如果没有虚继承,会导致基类数据成员在派生类中有多份副本,可能引起二义性等问题。虚继承可以保证在这种复杂的继承关系中,公共基类只有一份副本。
  2. 简单的虚继承示例

    • 首先看一个没有虚继承导致数据成员重复的例子:
    • cpp
class Base {
public:int baseData;
};class Derived1 : public Base {
};class Derived2 : public Base {
};class GrandDerived : public Derived1, public Derived2 {
};int main() {GrandDerived gd;// 下面这行代码会产生二义性错误,因为baseData在Derived1和Derived2中都存在// gd.baseData = 10;return 0;
}

  • 在这个例子中,GrandDerived类通过Derived1Derived2间接继承了Base类,这就导致GrandDerived对象中有两份Base类的数据成员baseData。当试图访问baseData时会产生二义性错误。

  1. 使用虚继承解决菱形继承问题

    • 下面是使用虚继承来解决上述问题的代码
    • cpp
class Base {
public:int baseData;
};class Derived1 : virtual public Base {
};class Derived2 : virtual public Base {
};class GrandDerived : public Derived1, public Derived2 {
};int main() {GrandDerived gd;gd.baseData = 10;  // 正确,此时只有一份baseDatareturn 0;
}
  • 在这个修改后的代码中,Derived1Derived2虚继承自Base类。这使得在GrandDerived类中,Base类只会有一份副本,所以可以正确地访问baseData成员。

  1. 虚继承的构造函数顺序案例

    • 当涉及虚继承时,构造函数的调用顺序也有特殊的规则。构造函数的调用顺序是先调用虚基类的构造函数,然后再按照继承顺序调用非虚基类的构造函数。
    • cpp
class Base {
public:Base() {std::cout << "Base constructor" << std::endl;}
};class Derived1 : virtual public Base {
public:Derived1() {std::cout << "Derived1 constructor" << std::endl;}
};class Derived2 : virtual public Base {
public:Derived2() {std::cout << "Derived2 constructor" << std::endl;}
};class GrandDerived : public Derived1, public Derived2 {
public:GrandDerived() {std::cout << "GrandDerived constructor" << std::endl;}
};int main() {GrandDerived gd;return 0;
}
  • 在这个例子中,输出结果是:
Base constructor
Derived1 constructor
Derived2 constructor
GrandDerived constructor
  • 可以看到,首先调用了虚基类Base的构造函数,然后按照继承顺序调用了Derived1Derived2的构造函数,最后调用了GrandDerived的构造函数。

  1. 虚继承中的指针和引用案例

    • 考虑以下代码来展示虚继承中指针和引用的行为:
    • cpp
class Base {
public:int baseData;virtual void print() {std::cout << "Base print" << std::endl;}
};class Derived1 : virtual public Base {
public:void print() override {std::cout << "Derived1 print" << std::endl;}
};class Derived2 : virtual public Base {
public:void print() override {std::cout << "Derived2 print" << std::endl;}
};class GrandDerived : public Derived1, public Derived2 {
};int main() {GrandDerived gd;Base* ptr = &gd;ptr->print();  // 调用Derived1的print函数,这取决于继承顺序和虚函数机制return 0;
}
  • 在这个例子中,通过Base*指针指向GrandDerived对象,当调用print函数时,由于虚函数的动态绑定特性和继承顺序,实际上调用的是Derived1类中的print函数。这展示了在虚继承场景下,通过基类指针或引用访问虚函数时的多态行为。

以下是用流程图来说明虚继承用于解决多继承时菱形继承问题的过程:

graph TD;A[定义基类Base] --> B[定义子类Derived1和Derived2直接继承Base];B --> C[定义GrandDerived类继承Derived1和Derived2形成菱形继承结构];C --> D[不使用虚继承时,GrandDerived对象中有两份Base类的数据成员,访问可能出现二义性];A --> E[定义子类Derived1和Derived2虚继承Base];E --> F[定义GrandDerived类继承Derived1和Derived2];F --> G[使用虚继承后,Base类在GrandDerived对象中只有一份副本,可正常访问数据成员];

在上述流程图中:

  • 首先是定义一个基类Base
  • 然后有两种情况分支:
    • 一种是常规的非虚继承方式,Derived1Derived2直接继承Base,之后GrandDerived再继承Derived1Derived2,这样会形成菱形继承结构,并且在不使用虚继承时,GrandDerived对象中会存在两份Base类的数据成员,导致在访问这些数据成员时可能出现二义性问题。
    • 另一种是采用虚继承的方式,Derived1Derived2虚继承Base,接着GrandDerived继承Derived1Derived2,此时由于虚继承的作用,Base类在GrandDerived对象中只会有一份副本,从而可以正常地访问数据成员,避免了二义性等问题。

相关文章:

c++的虚继承说明、案例、代码

虚继承的基本概念 在 C 中&#xff0c;虚继承主要用于解决多继承时可能出现的菱形继承问题。菱形继承是指一个类有两个&#xff08;或更多&#xff09;子类&#xff0c;而这两个子类又同时继承自一个共同的基类&#xff0c;当这些子类又被另一个类继承时&#xff0c;就形成了菱…...

小米PC电脑手机互联互通,小米妙享,小米电脑管家,老款小米笔记本怎么使用,其他品牌笔记本怎么使用,一分钟教会你

说在前面 之前我们体验过妙享中心&#xff0c;里面就有互联互通的全部能力&#xff0c;现在有了小米电脑管家&#xff0c;老款的笔记本竟然用不了&#xff0c;也可以理解&#xff0c;毕竟老款笔记本做系统研发的时候没有预留适配的文件补丁&#xff0c;至于其他品牌的winPC小米…...

介绍SSD硬盘

SSD硬盘&#xff08;固态硬盘&#xff0c;Solid State Drive&#xff09;是一种利用闪存技术存储数据的存储设备&#xff0c;与传统的机械硬盘&#xff08;HDD&#xff09;不同&#xff0c;SSD没有任何活动部件&#xff0c;因此其性能和耐用性较为优越。以下是SSD硬盘的一些主要…...

CMAKE常用命令详解

NDK List基本用法 Get–获取列表中指定索引的元素 list(Get list_name index output_var)解释 list_name: 要操作集合的名称index: 要取得的元素下标output_var: 保存从集合中取得元素的结果 栗子 list(GET mylist 0 first_element) # 获取第一个元素APPEND–在列表末尾…...

Vue3的通灵之术Teleport

前言 近期Vue3更新了一些新的内容&#xff0c;我都还没有一个一个仔细去看&#xff0c;但是还是有必要去解读一下新内容的。就先从Teleport 开始吧。 官方对 Teleport 的解释是&#xff1a;<Teleport> 是一个内置组件&#xff0c;它可以将一个组件内部的一部分模板“传…...

ue5第三人称闯关游戏学习(一)

视频资料38 - Compilers and Editors_哔哩哔哩_bilibili 上一个第一人称射击项目做完 接下来要更深入学习。 引入资产与C来创建第三人称闯关游戏 这次要引入的资产有两个分别是 Unreal Learning Kit&#xff1a;Game和stylized character kit: casual 01 不过有个比较麻…...

IIC 随机写+多次写 可以控制写几次

verilog module icc_tx#(parameter SIZE 2 , //用来控制写多少次 比如地址是0000 一个地址只能存放8bit数据 超出指针就会到下一个地址0001parameter CLK_DIV 50_000_000 ,parameter SPEED 100_000 ,parameter LED 50 )( input wire c…...

controller中的参数注解@Param @RequestParam和@RequestBody的不同

现在controller中有个方法&#xff1a;&#xff08;LoginUserRequest是一个用户类对象&#xff09; PostMapping("/test/phone")public Result validPhone(LoginUserRequest loginUserRequest) {return Result.success(loginUserRequest);}现在讨论Param("login…...

手搓人工智能-最优化算法(1)最速梯度下降法,及推导过程

“Men pass away, but their deeds abide.” 人终有一死&#xff0c;但是他们的业绩将永存。 ——奥古斯坦-路易柯西 目录 前言 简单函数求极值 复杂函数梯度法求极值 泰勒展开 梯度&#xff0c;Nabla算子 Cauchy-Schwarz不等式 梯度下降算法 算法流程 梯度下降法…...

多目标优化算法——多目标粒子群优化算法(MOPSO)

Handling Multiple Objectives With Particle Swarm Optimization&#xff08;多目标粒子群优化算法&#xff09; 一、摘要&#xff1a; 本文提出了一种将帕累托优势引入粒子群优化算法的方法&#xff0c;使该算法能够处理具有多个目标函数的问题。与目前其他将粒子群算法扩展…...

Swift——自动引用计数ARC

ARC ARC是swift使用的一种管理应用程序内存的机制&#xff0c;对于C语言我们知道&#xff0c;当我们申请一块空间&#xff0c;通常需要手动释放&#xff0c;不然会造成空间浪费&#xff0c;而有了ARC机制&#xff0c;你无需考虑内存的管理&#xff0c;因为ARC会在类的实例不再…...

【Quarkus】基于CDI和拦截器实现AOP功能(进阶版)

Quarkus 基于CDI和拦截器实现AOP功能&#xff08;进阶版&#xff09; 拦截器的属性成员拦截器的重复使用基于属性成员和重复使用的拦截器的发消息案例 本节来了解一下拦截器高级特性&#xff08;拦截器的重复使用和属性成员&#xff09;&#xff0c;官网说明&#xff1a;https:…...

【踩坑日记】【教程】如何在ubuntu服务器上配置公钥登录以及bug解决

前言 在日常开发和运维中&#xff0c;为了提高服务器登录的安全性&#xff0c;我们通常会选择使用 SSH 密钥认证 来替代传统的密码登录。然而&#xff0c;在配置 SSH 公钥登录的过程中&#xff0c;可能会遇到各种坑和 Bug。本文将从零开始&#xff0c;手把手教你如何在 Ubuntu…...

insmod一个ko提供基础函数供后insmod的ko使用的方法

一、背景 在内核模块开发时&#xff0c;多个不同的内核模块&#xff0c;有时候可能需要都共用一些公共的函数&#xff0c;比如申请一些平台性的公共资源。但是&#xff0c;这些公共的函数又不方便去加入到内核镜像里&#xff0c;这时候就需要把这些各个内核模块需要用到的一些…...

七、传统循环神经网络(RNN)

传统循环神经网络 RNN 前言一、RNN 是什么&#xff1f;1.1 RNN 的结构1.2 结构举例 二、RNN 模型的分类2.1 按照 输入跟输出 的结构分类2.2 按照 内部结构 分类 三、传统 RNN 模型3.1 RNN内部结构图3.2 内部计算公式3.3 其中 tanh 激活函数的作用3.4 传统RNN优缺点 四、代码演示…...

LeetCode:19.删除链表倒数第N个节点

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;19.删除链表倒数第N个节点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表…...

【RISC-V CPU debug 专栏 2 -- Debug Module (DM), non-ISA】

文章目录 调试模块(DM)功能必须支持的功能可选支持的功能兼容性要求规模限制Debug Module Interface (DMI)总线类型地址与操作地址空间控制机制Debug Module Interface Signals请求信号响应信号信号流程Reset Control复位控制方法全局复位 (`ndmreset`)Hart 复位 (`hartreset…...

单片机学习笔记 11. 外部中断

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…...

基于stm32的智能教室管理系统/智能家居系统

基于stm32的智能教室管理系统/智能家居系统 持续更新&#xff0c;欢迎关注!!! ** 基于stm32的智能教室管理系统/智能家居系统 ** 目前&#xff0c;物联网已广泛应用在我们的生活中。智慧校园是将校园中的生活、学习、工作等相关的资源联系在一起&#xff0c;实现管理的智能化…...

基于 Qt 和 GStreamer 的环境中构建播放器

一、功能与需求分析 功能描述 播放本地视频文件(如 MP4、MKV)。 支持基本控制功能(播放、暂停、停止、跳转)。 提供音量调节功能。 在 Windows 环境下使用 Visual Studio 2022 编译。 技术选型 Qt:用于构建用户界面。 GStreamer:负责视频解码和播放。 Visual Studio 202…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...