C++ ---- 虚继承

news2025/4/3 0:04:07

一、什么是虚继承

        虚继承就是子类中只有一份间接父类的数据。用于解决多继承中的父类为非虚继承时出现的二义性问题,即菱形继承问题。继承方式需要加上virtual关键字。

二、虚继承的特性

以菱形继承为例:

1.不使用虚继承

根据输出的大小和关系图,可以看出student和employee继承的是同一个person,但是在结构中有两个person,造成了二义性。

class Person {
private:
	int _pid;
	char _sex;
};

class Student :public Person {
private:
	int _sid;
};

class Employee :public Person {
private:
	int _eid;
};

class EStudent :public Student, public Employee {
private: int _egid;
};
int main() {
	cout << sizeof(Person) << endl;
	cout << sizeof(Student) << endl;
	cout << sizeof(Employee) << endl;
	cout << sizeof(EStudent) << endl;

}

2.使用虚继承

使用虚继承之后,就可以看出student和employee继承的是同一个person,并且不会导致二义性

class Person {
private:
	int _pid;
	char _sex;
};

class Student :virtual public Person {
private:
	int _sid;
};

class Employee :virtual public Person {
private:
	int _eid;
};

class EStudent :public Student,public Employee {
private: int _egid;
};

三、虚继承原理

在上述实例中,我们发现父类数据并不存放在虚继承的子类中,那么子类怎么找到父类数据呢?

原因是在虚继承的类中,会定义一个虚基表指针vbptr指向虚基表。而虚基表中会存在偏移量,这个量就是表的地址到父类数据地址的距离。当一个类虚继承自另一个类时,子类对象中会包含一个虚基类指针(vbptr)。这个指针指向一个虚基类表(vbtable)。虚基类表中存储了虚基类子对象相对于子类对象的偏移量等信息。通过虚基类指针找到虚基类表,再根据表中的偏移量信息,就可以在子类对象的内存空间中定位到虚基类(父类)的数据成员。

四、虚函数与虚继承

虚函数和虚继承并不是一个概念:

  • 虚函数:是在基类中使用virtual关键字声明的成员函数,它允许在派生类中被重新定义(重写),以实现不同的行为。
  • 虚继承:是一种继承方式,用于解决多继承中可能出现的菱形继承问题,确保从多个基类继承而来的同一个基类子对象在派生类中只有一份拷贝。

原理:

  • 虚函数:通过虚函数表(vtable)和虚函数表指针(vptr)来实现。每个包含虚函数的类都有一个虚函数表,其中存储了该类所有虚函数的地址。对象中包含一个虚函数表指针,指向所属类的虚函数表,以便在运行时能够动态地查找和调用正确的虚函数。
  • 虚继承:编译器会为虚继承的基类子对象创建一个隐藏的指针,称为虚基表指针(vbptr),它指向一个虚基表(vbtable)。虚基表中存储了虚基类子对象相对于派生类对象的偏移量等信息,通过这些信息可以在运行时正确地访问虚基类子对象。

我们再来说一下虚函数表的存储方式:

虚函数表在编译时产生,存放在只读数据段(每一个类的虚表不可更改),每一个类对应一个虚表,而每一个类的所有对象共享同一个虚表。

虚函数表的存储方式是一个指针数组,它本质上是一个数组,而每一个数组元素都是一个指针,指向对应的虚函数地址。

当通过对象指针或引用调用虚函数时,程序会先通过对象内的虚表指针找到虚表,再从虚表中获取对应虚函数的指针,进而调用该函数,以此实现运行时多态。

五、构造函数和析构函数是否可以写为虚继承

1.构造函数

构造函数的用途:1)创建对象;2)初始化对象中的属性;3)类型转换;4)在定义对象时构造函数设置虚表指针指向虚函数表

2.析构函数

析构函数是类的一个特殊的成员函数:

  • 当一个对象的生命周期结束时,系统会自动调用析构函数注销该对象并进行善后工作,对象自身也可以调用析构函数;
  • 析构函数的善后工作是:释放对象在生命周期内获得的资源(如动态分配的内存,内核资源);
  • 析构函数也用来执行对象即将被撤销之前的任何操作

根据赋值兼容规则,可以用基类的指针指向派生类对象,如果使用基类型指针指向动态创建的派生类对象,由该基类指针撤销派生类对象,则必须将析构函数定义为虚函数,实现多态性,自动调用派生类析构函数,否则可能存在内存泄漏问题

类中没有虚函数,就不要把析构函数定义为虚。

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2326861.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

启幕数据结构算法雅航新章,穿梭C++梦幻领域的探索之旅——堆的应用之堆排、Top-K问题

人无完人&#xff0c;持之以恒&#xff0c;方能见真我&#xff01;&#xff01;&#xff01; 共同进步&#xff01;&#xff01; 文章目录 一、堆排引入之使用堆排序数组二、真正的堆排1.向上调整算法建堆2.向下调整算法建堆3.向上和向下调整算法建堆时间复杂度比较4.建堆后的排…

forms实现俄罗斯方块

说明&#xff1a; 我希望用forms实现俄罗斯方块 效果图&#xff1a; step1:C:\Users\wangrusheng\RiderProjects\WinFormsApp2\WinFormsApp2\Form1.cs using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms;namespace WinFor…

PHP回调后门

1.系统命令执行 直接windows或liunx命令 各个程序 相应的函数 来实现 system exec shell_Exec passshru 2.执行代码 eval assert php代码 系统 <?php eval($_POST) <?php assert($_POST) 简单的测试 回调后门函数call_user_func(1,2) 1是回调的函数 2是回调…

实操自动生成接口自动化测试用例

​这期抽出来的问题是关于如何使用Eolinker自动生成接口自动化测试用例&#xff0c;也就是将API文档变更同步到测试用例&#xff0c;下面是流程的示例解析。 导入并关联API文档和自动化测试用例 首先是登陆Eolinker&#xff0c;可以直接在线使用。 进入流程测试用例详情页&am…

Python数据类型-dict

Python数据类型-dict 字典是Python中一种非常强大且常用的数据类型&#xff0c;它使用键-值对(key-value)的形式存储数据。 1. 字典的基本特性 无序集合&#xff1a;字典中的元素没有顺序概念可变(mutable)&#xff1a;可以动态添加、修改和删除元素键必须唯一且不可变&…

0301-组件基础-react-仿低代码平台项目

文章目录 1 组件基础2 组件props3 React开发者工具结语 1 组件基础 React中一切都是组件&#xff0c;组件是React的基础。 组件就是一个UI片段拥有独立的逻辑和显示组件可大可小&#xff0c;可嵌套 组件的价值和意义&#xff1a; 组件嵌套来组织UI结构&#xff0c;和HTML一…

18-背景渐变与阴影(CSS3)

知识目标 理解背景渐变的概念和作用掌握背景渐变样式属性的语法与使用理解阴影效果的原理和应用场景掌握阴影样式属性的语法与使用 1. 背景渐变 1.1 线性渐变 运用CSS3中的“background-image:linear-gradient&#xff08;参数值&#xff09;;”样式可以实现线性渐变效果。 …

UE5学习记录part12

第15节&#xff1a; treasure 154 treasure: spawn pickups from breakables treasure是items的子类 基于c的treasure生成蓝图类 155 spawning actors: spawning treasure pickups 设置treasure的碰撞 蓝图实现 156 spawning actors from c &#xff1a; spawning our treas…

鸿蒙开发03样式相关介绍(一)

文章目录 前言一、样式语法1.1 样式属性1.2 枚举值 二、样式单位三、图片资源3.1 本地资源3.2 内置资源3.3 媒体资源3.4 在线资源3.5 字体图标3.6 媒体资源 前言 ArkTS以声明方式组合和扩展组件来描述应用程序的UI&#xff0c;同时还提供了基本的属性、事件和子组件配置方法&a…

一周掌握Flutter开发--9. 与原生交互(上)

文章目录 9. 与原生交互核心场景9.1 调用平台功能&#xff1a;MethodChannel9.1.1 Flutter 端实现9.1.2 Android 端实现9.1.3 iOS 端实现9.1.4 使用场景 9.2 使用社区插件9.2.1 常用插件9.2.2 插件的优势 总结 9. 与原生交互 Flutter 提供了强大的跨平台开发能力&#xff0c;但…

鸿蒙阔折叠Pura X外屏开发适配

首先看下鸿蒙中断点分类 内外屏开合规则 Pura X开合连续规则: 外屏切换到内屏,界面可以直接接续。内屏(锁屏或非锁屏状态)切换到外屏,默认都显示为锁屏的亮屏状态。用户解锁后:对于应用已适配外屏的情况下,应用界面可以接续到外屏。折叠外屏显示展开内屏显示折叠状态…

小程序中跨页面组件共享数据的实现方法与对比

小程序中跨页面/组件共享数据的实现方法与对比 在小程序开发中&#xff0c;实现不同页面或组件之间的数据共享是常见需求。以下是几种主要实现方式的详细总结与对比分析&#xff1a; 一、常用数据共享方法 全局变量&#xff08;getApp()&#xff09;、本地缓存&#xff08;w…

Java 大视界 -- 基于 Java 的大数据分布式计算在基因测序数据分析中的性能优化(161)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

DeepSeek-R1 模型现已在亚马逊云科技上提供

2025年3月10日更新—DeepSeek-R1现已作为完全托管的无服务器模型在Amazon Bedrock上提供。 2025年2月5日更新—DeepSeek-R1 Distill Llama 和 Qwen模型现已在Amazon Bedrock Marketplace和Amazon SageMaker JumpStart中提供。 在最近的Amazon re:Invent大会上&#xff0c;亚马…

Python数据可视化-第2章-使用matplotlib绘制简单图表

环境 开发工具 VSCode库的版本 numpy1.26.4 matplotlib3.10.1 ipympl0.9.7教材 本书为《Python数据可视化》一书的配套内容&#xff0c;本章为第2章 使用matplotlib绘制简单图表 本文主要介绍了折线图、柱形图或堆积柱形图、条形图或堆积条形图、堆积面积图、直方图、饼图或…

Redis 02

今天是2025/04/01 20:13 day 16 总路线请移步主页Java大纲相关文章 今天进行Redis 3,4,5 个模块的归纳 首先是Redis的相关内容概括的思维导图 3. 持久化机制&#xff08;深度解析&#xff09; 3.1 RDB&#xff08;快照&#xff09; 核心机制&#xff1a; 触发条件&#xff…

unity UI管理器

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events;// UI界面基类 public abstract class UIBase : MonoBehaviour {[Header("UI Settings")]public bool keepInStack true; // 是否保留在界面栈中public …

STRUCTBERT:将语言结构融入预训练以提升深度语言理解

【摘要】最近&#xff0c;预训练语言模型BERT&#xff08;及其经过稳健优化的版本RoBERTa&#xff09;在自然语言理解&#xff08;NLU&#xff09;领域引起了广泛关注&#xff0c;并在情感分类、自然语言推理、语义文本相似度和问答等各种NLU任务中达到了最先进的准确率。受到E…

16-CSS3新增选择器

知识目标 掌握属性选择器的使用掌握关系选择器的使用掌握结构化伪类选择器的使用掌握伪元素选择器的使用 如何减少文档内class属性和id属性的定义&#xff0c;使文档变得更加简洁&#xff1f; 可以通过属性选择器、关系选择器、结构化伪类选择器、伪元素选择器。 1. 属性选择…

SQL Server:用户权限

目录 创建 & 删除1. 创建用户命令整理创建 admin2 用户创建 admin_super 用户 2. 删除用户命令删除 admin2 用户删除 admin_super 用户 3. 创建时权限的区别admin2 用户权限admin_super 用户权限 查看方法一&#xff1a;使用对象资源管理器&#xff08;图形化界面&#xff…