C++从入门到入土(八)——多态的原理
目录
前言
多态的原理
动态绑定与静态绑定
虚函数表
小结
前言
在前面的文章中,我们介绍了C++三大特性之一的多态,我们主要介绍了多态的构成条件,但是对于多态的原理我们探讨的是不够深入的,下面这这一篇文章,我们将着重介绍C++多态的实现原理。
相关参考文章如下:
C++从入门到入土(七)——多态
多态的原理
我们在前面的文章中了解到多态的实现条件有以下两个:
1.必须是基类的指针或引用调用虚函数
2.被调用的函数必须是虚函数,并且完成了重写
看到上面两个条件,我们不禁会发出疑问,为什么必须是通过基类的指针或引用调用虚函数呢?为什么不能通过其他条件构成多态呢?那么我们通过下面代码来讨论这两个问题:
class Base
{
public:virtual void Func(){cout << "基类调用" << endl;}
protected:int _base;
};class A:public Base
{
public:virtual void Func(){cout << "派生类调用" << endl;}
private:int _a;
};void Print(Base& a)
{a.Func();
}int main()
{Base b;Print(b);A a;Print(a);return 0;
}
首先我们看到上述一段简单的代码,其运行结果如下所示:
我们进入调试观察一下它的内部:
我们可以看到,相比于没有实现多态的类,其底层多了一个_vfptr的对象,那这个对象是什么呢?直接讲结论:这个对象是虚函数表(v表示virtual,f表示function,ptr表示指针),其本质是一个指针数组。
那么我们此时就可以猜测,是不是因为虚函数表的出现导致多态行为的发生呢?我们再仔细观察一下会发现,派生类的虚函数表保存在基类base之下,但是他们的地址是不同的,那么虚函数表中存储的是什么呢?实际上虚函数表中存的是虚函数的地址。当我们满足多态的条件后,我们在编译时不再通过调用对象来确定函数的地址,而是运行时到指向对象的虚函数表中确定虚函数的地址,这样就实现了基类的指针或引用调用不同函数的目的。
动态绑定与静态绑定
我们在粗略理解了多态的原理后,接下来我们引入动态绑定与静态绑定的概念帮助我们更加深入地理解多态地原理.。
首先我们要理解什么是动态与静态绑定。
静态绑定:在编译时就确定函数的地址就叫静态绑定,换句话说就是不满足多态的函数调用,例如:函数重载、模板等。
动态绑定:在运行时通过虚函数表来确定函数的地址就叫动态绑定,例如:多态。
所以可以这么说,动态绑定是多态的特点之一。
虚函数表
还是以上面的例子,我们发现,派生类和基类在实例化的过程中分别产生了不同的虚函数表,即使派生类继承了基类的对象,但是派生类的虚函数表中并没有保存基类虚函数的地址,我们将虚函数表的地址输入到内存窗口中查看:
我们可以看到,基类和派生类的虚函数表中保存的地址是不同的,不同的类的虚表也是不同的。
我们给派生类再加一个虚函数,进入调试,观察一下:
当我们给基类添加了一个虚函数后发现,虚函数表中又存储了一个地址,但是对于基类而言只有一个虚函数的地址,那么我们可以得出下面的结论:
派生类的虚函数表中包含<1.>基类虚函数的地址 <2.>派生类重写的虚函数的地址的覆盖 <3.>自己的虚函数的地址
综上所述,对于虚函数表的结论如下:
1.基类对象的虚函数表存放基类所有虚函数的地址,同类型的对象共用一张虚函数表,不同类型的对象各有自己的虚函数表,即:基类和派生类各有自己的虚函数表
2.虚函数表中包含:基类虚函数的地址; 派生类重写的虚函数的地址的覆盖; 派生类自己的虚函数
3.虚函数表本质是一个函数指针数组,存放虚函数的地址
4.虚函数存放在代码段,虚函数的地址存放在虚函数表,虚函数表指针存放在对象中
小结
本篇文章我们介绍了多态的实现原理,动态绑定以及虚函数表,通过本篇博客的阅读相信您对多态的认识会更加清楚,如果本篇文章对您有所帮助的话希望能够点赞、关注加转发,您的支持就是我创作的最大动力。
相关文章:
C++从入门到入土(八)——多态的原理
目录 前言 多态的原理 动态绑定与静态绑定 虚函数表 小结 前言 在前面的文章中,我们介绍了C三大特性之一的多态,我们主要介绍了多态的构成条件,但是对于多态的原理我们探讨的是不够深入的,下面这这一篇文章,我们将…...
BFS,DFS带图详解+蓝桥杯算法题+经典例题
1.BFS和DFS的定义与实现方式 1.1 深度优先搜索(DFS) 基本概念:DFS 是一种用于遍历或搜索图或树的算法。它从起始节点开始,沿着一条路径尽可能深地探索下去,直到无法继续或者达到目标节点,然后回溯到上一个…...
【RHCE实验】搭建主从DNS、WEB等服务器
目录 需求 环境搭建 配置nfs服务器 配置web服务器 配置主从dns服务器 主dns服务器 从dns服务器 配置客户端 客户端测试 需求 客户端通过访问 www.nihao.com 后,能够通过 dns 域名解析,访问到 nginx 服务中由 nfs 共享的首页文件,内容…...
有哪些开源的智慧园区项目?
作为专注于数字孪生技术的开发者团队,我们一直在数字孪生圈分享开源项目。但最近一次与AI助手Deepseek的对话,却让我们“又惊又喜”。 ——当询问“有哪些开源的智慧园区项目”时,Deepseek的回答中竟包含了我们自己的开源项目! 这…...
prometheusalert对阿里云短信服务不适配问题处理
背景 想通过prometheusalert实现阿里云短信告警。结果在配置完altermanager和prometheusalert,以及阿里云短信服务中的各种签名和短信模板之后,在prometheusalert web ui上测试模板时一直报“模板变量JSON格式错误 或 JSON变量属性与模板占位符不一致”…...
NFC 碰一碰发视频源码搭建,支持OEM
一、引言 NFC(Near Field Communication)近场通信技术,以其便捷、快速的数据交互特性,正广泛应用于各个领域。其中,NFC 碰一碰发视频这一应用场景,为用户带来了新颖且高效的视频分享体验。想象一下&#x…...
浅谈鸿蒙跨平台开发框架ArkUI-X
之前写过使用uniapp的跨平台开发鸿蒙项目,今天分享一下开发体验更友好的跨平台开发框架ArkUI-X。 ArkUI-X看起来像是鸿蒙官方的框架,在DevEco中就可以安装和使用,而且会ArkUI就可以开发安卓和、iOS和鸿蒙三个平台的app,下面简单介…...
LLVM学习-- 构建和安装
一 LLVM版本 二 适用预构建的二进制文件安装LLVM 三 适用包管理器安装LLVM 四 从源码构建用于Linux的LLVM 五 从源码构建用于Windows和Visual Studio的LLVM 六 从源码构建用于MacOS 和XCode的LLVM 1.1 LLVM项目从10年前第一次发布到版本3.4,其SVN存储库包含了超过20…...
总结Solidity 的数据类型
数据类型 在 Solidity 中,类型系统非常丰富,主要分为 值类型(Value Types)和 引用类型(Reference Types)。此外,还有一些特殊类型和全局变量。 一.值类型 布尔型(bool)…...
C# 中泛型(Generics)的核心概念
在 C# 中,泛型(Generics) 是一种强大的编程特性,允许你编写可重用、类型安全的代码,而无需为不同类型重复编写相似的逻辑。泛型的核心思想是参数化类型,即通过占位符(如 T)表…...
ubuntu 根据src 包从新打包
下边以onnxruntime示例: 1. 安装必要的依赖 确保你的系统已安装 devscripts、dpkg-dev 和 build-essential: sudo apt update sudo apt install devscripts dpkg-dev build-essential equivs2. 解压源码 进入存放源码包的目录,并解压: #c…...
如何启用 HTTPS 并配置免费的 SSL 证书
引言 HTTPS 已成为现代网站安全性的基础要求。通过 SSL/TLS 证书对数据进行加密,不仅可以保护用户隐私,还能提升搜索引擎排名并增强用户信任。本指南将详细介绍如何通过 Lets Encrypt(免费、自动化的证书颁发机构)为您的网站启用…...
Python数据与变量、进制转换、输入输出函数、基本运算,基础语法编程练习
第一节 数据与变量 程序 数据 指令 1.1 内置基本数据类型 (1)数值型 整数(int):用于表示整数,注意一点Python中int数据可以存储任意大小整数,不会像其他语言(C\C Java࿰…...
联邦学习(Federated Learning)
1. 概念 联邦学习(Federated Learning, FL)是一种分布式机器学习技术,它允许多个参与方(如设备、机构或企业)在不共享原始数据的情况下协同训练机器学习模型。联邦学习通过本地计算模型参数聚合的方式,保护…...
AI大模型核心原理(二)
一、人工智能的兴起。 1、前序。 艾伦麦席森图灵; 是计算机科学之父。 著名英国数学家、计算机科学家、逻辑学家和密码分析学家,被誉为计算机科学与人工智能之父。 阿兰・图灵(Alan Turing) 是译名(简称)…...
数据结构篇——线索二叉树
一、引入 遍历二叉树是按一定规则将二叉树结点排成线性序列,得到先序、中序或后序序列,本质是对非线性结构线性化,使结点(除首尾)在线性序列中有唯一前驱和后继;但以二叉链表作存储结构时,只能获…...
【蓝桥杯】742合唱队形(DP LIS)
思路 借这题复习一下LIS,实际上是LIS的升级版,求一个\/形或者/\行,用两次最长上升子串即可。 先从前往后求递增,再从后往前求递减。 先把满足要求的最长队形求出来,总人数减去队形人数就是要出列的数目。 code impo…...
MySQL二进制日志格式有哪几种
目录 一、二进制日志格式类型1. **STATEMENT 格式(SBR: Statement-Based Replication)**2. **ROW 格式(RBR: Row-Based Replication)**3. **MIXED 格式(混合模式)**二、二进制日志事件详解三、如何选择二进制日志格式?四、配置与查看二进制日志格式五、注意事项在 MySQL…...
VUE管理后台开发-vue-element-admin
# 克隆项目 git clone https://github.com/PanJiaChen/vue-element-admin.git # 进入项目目录 cd vue-element-admin # 安装依赖 npm install # 速度过慢可以使用下面方法进行指定下载镜像原 # 也可以使用nrm选择下载镜像原 # 建议不要用 cnpm 安装 会有各种诡异的bug 可以通…...
计算机网络原理
网络发展史 起初,计算机之间是相互独立的,分别完成不同的工作,效率较为低下.随着时代的发展,计算机开始协同完成任务,就有了网络互连.网络互连是指将多台计算机连接在一起,完成数据共享.根据网络互联的规模不同,可以划分为局域网和广域网.局域网,简称LAN.局域网内的主机可以互相…...
速盾:如何利用CDN静态加速匹配尾缀提升网站性能?
在当前数字化时代,网站性能对于用户体验至关重要。尤其是对于包含大量静态资源(如图片、CSS、JavaScript文件等)的网站来说,如何高效地管理和加速这些资源成为了一个重要课题。本文将介绍如何利用CDN静态加速匹配尾缀的方法来提升…...
【H2O2 | 软件开发】前端深拷贝的实现
目录 前言 开篇语 准备工作 正文 概述 JSON方法 递归 其他 结束语 前言 开篇语 本系列为短篇,每次讲述少量知识点,无需一次性灌输太多的新知识点。该主题文章主要是围绕前端、全栈开发相关面试常见问题撰写的,希望对诸位有所帮助。…...
C#语法基础总结
输入和输出 输入 Console.Read(); 从屏幕读取一个字符,并返回该字符所对应的整型数字 Console.ReadLine(); 从屏幕读取一串字符,并返回该字符串 输出 Console.WriteLine(); 输出内容,并换行 Console.Write(); 输出内容,不换行…...
《深度学习》—— 模型部署
文章目录 模型部署模型准备选择部署平台部署配置与服务化测试与验证优化与维护常用工具与框架Flask本地部署模型 模型部署 模型部署是将训练好的机器学习或深度学习模型投入实际生产环境,使其能够处理实时数据并提供预测或推理服务的过程。 模型准备 模型格式转换…...
E902基于bash与VCS的仿真环境建立
网上看见很多E902仿真的文章,但用到的编译器是类似于这种Xuantie-900-gcc-elf-newlib-x86_64-V3.0.1-20241120,而我按照相应的步骤与对应的编译器,仿真总会报错。后面将编译器换成riscv64-elf-x86_64-20210512,反而成功了。现在开…...
挖矿------获取以太坊测试币
文章目录 挖矿------获取以太坊测试币通过水龙头获取以太坊测试币了解Sepolia是什么?水龙头(Faucet)是什么?Gitcoin Passport是什么? 操作1.MetaMask钱包2.将MetaMask切换到Sepolia测试网络3.用MetaMask连接Gitcoin Pa…...
MySQL事务详解:从理论到实践,保障数据一致性
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、为什么需要事务?二、事务的四大特性(ACID)三、MySQL事务的使用方法1. 基本语法2. 自动提交的设置3. 保存点(…...
在家用台式机上部署 DeepSeek-R1:低成本高性能的 CPU 推理方案---不到 4 万元
近年来,随着大模型技术的飞速发展,开源模型如 DeepSeek-R1 的出现为技术爱好者提供了更多探索人工智能的机会。然而,这类模型动辄数百亿参数,传统意义上需要昂贵的 GPU 集群才能运行,让许多个人开发者望而却步。最近,腾讯玄武实验室基于 CPU 的硬件方案优化,成功将 Deep…...
神经网络量化3-全连接层实现量化
本节,我们模拟下全连接层实现量化,原理上为了方便计算,全连接矩阵采用动态量化的方法,而输入由于不断在变化,我们采用静态量化的方法,直接给出代码: import torch import numpy as np import m…...
12 File文件对象:创建、获取基本信息、遍历文件夹、查找文件;字符集的编解码 (黑马Java视频笔记)
文章目录 File >> 存储数据的方案1. 认识File2. File操作2.1 创建File对象2.2 File操作1)对文件对象的信息的操作2)文件/文件夹的创建/删除3)⭐⭐对文件夹的遍历 3. 方法递归3.1 认识递归3.2 递归算法及其执行流程1) 案例:2…...
【软件工程】03_软件需求分析
3.1 系统分析 1. 系统分析概述 系统分析是一组统称为计算机系统工程的活动。它着眼于所有的系统元素,而非仅仅局限于软件。系统分析主要探索软件项目的目标、市场预期、主要的技术指标等,其目的在于帮助决策者做出是否进行软件项目立项的决定。 2. 可行性分析(Feasibility …...
词向量+位置编码=语义+语序?Transformer如何让相加操作不丢失原意?
在Transformer模型中,词向量(Token Embedding)和位置编码(Position Encoding)通过相加的方式结合,而模型能够同时保留词本身的语义信息和位置信息,这主要得益于以下机制: 为什么相加…...
Spring(7)——MyBatis入门(1)
一、MyBatis入门 1.1 什么是MyBatis MyBatis是一款优秀的持久层框架,用于简化JDBC的开发。 1.2 如何操作MyBatis 在application.properties进行配置 #驱动类名称 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver #数据库连接的url spring.datasou…...
C语言文件操作入门
本节重点 理解文件的形式与基本概念二进制文件与文本文件文件的打开与关闭文件读写函数、文件缓冲区 正文开始--------------------------------------------------------------------------------------------------------------------- 一、为什么使用文件 程序运行时数据存…...
Java返回多个参数的方法
背景 在写代码的过程中,因有一些复杂的业务逻辑,需要返回多个结果。比如:需要增加一个true或者false,另外在加一个真正的结果值这样的类型。可能会有人用到数组以及Map等作为结果返回,当然这样确实是可以完成这样的功…...
微软开源神器OmniParser V2.0 介绍
微软开源的OmniParser V2.0是一款基于纯视觉技术的GUI智能体解析工具,旨在将用户界面(UI)截图转换为结构化数据,从而实现对计算机屏幕上的可交互元素的高效识别和操控。这一工具通过结合先进的视觉解析技术和大型语言模型…...
Java基础关键_023_IO流(一)
目 录 一、概述 二、分类 1.根据数据流向 2.根据读写数据形式 3.根据流在 IO 操作中的作用和实现方式 三、FileInputStream 1.说明 2.常用方法 (1)read() (2)read(byte[] b) (3)read(byte[] b, …...
Lora 中 怎么 实现 矩阵压缩
Lora 中 怎么 实现 矩阵压缩 1. 导入必要的库 import torch import re from datasets import Dataset from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer, \get_cosine_schedule_with_warmup, EarlyStoppingCallback from peft...
lombok不起作用
xml <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.32</version> <scope>provided</scope> </dependency> - **作用**:引入 L…...
【实战ES】实战 Elasticsearch:快速上手与深度实践-附录-1-常用命令速查表-集群健康检查、索引生命周期管理、故障诊断命令
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 附录-常用命令速查表 1-Elasticsearch 运维命令速查表(集群健康检查、ILM管理、故障诊断)一、集群健康检查与监控1.1 集群健康状态核心命令1.2 节点级健康诊断…...
探讨Deveco Studio常见问题及解决方案,分享快速排障方法
以下是针对 DevEco Studio 开发工具的常见问题、解决方案及快速排障方法,覆盖环境配置、编译运行、调试等多个环节,助您高效解决开发中的“拦路虎”。 一、环境配置问题 1. 安装失败或卡顿 现象: 安装时进度条卡住,或提示“Faile…...
Spring设计模式 八股速记 高层模块底层模块 依赖倒置原则 开闭原则 接口隔离原则
目录 高层模块底层模块 一、定义与核心思想 二、实现方式 三、优点与价值 四、典型应用场景 五、与其他原则的关系 示例说明 依赖倒置原则 一、定义与核心思想 二、实现方式 三、优点与价值 四、典型应用场景 五、与其他原则的关系 示例说明 自己理解 开闭原则 …...
RISCV虚拟化环境搭建
概要 本文记搭建 RISCV 虚拟化环境的流程。 整体架构 我们使用 QEMU 来模拟 RISCV 的各种硬件扩展环境,通过 QEMU 启动 Ubuntu 作为我们的 Host 来在 Host 之中通过 KVMTOOL 来运行 Guest,学习 RISCV 的虚拟化。 目前我的 X86_64 主机使用的是 Ubunt…...
数据结构——串、数组和广义表
串、数组和广义表 1. 串 1.1 串的定义 串(string)是由零个或多个字符组成的有限序列。一般记为 S a 1 a 2 . . . a n ( n ≥ 0 ) Sa_1a_2...a_n(n\geq0) Sa1a2...an(n≥0) 其中,S是串名,单引号括起来的字符序列是串的值, a i a_i a…...
vue3 elementUi table自由渲染组件
文章目录 前言CustomTable如何使用tableColumn 属性h函数创建原生元素创建组件动态生成 前言 elementui中的table组件,表格中想要自由地渲染内容,是一种比较麻烦的事情,比如你表格中想要某一列插入一个button按钮,是不是要用插槽…...
Centos离线安装gcc
文章目录 Centos离线安装gcc1. gcc是什么?2. gcc下载地址3. gcc的安装4. 安装结果验证 Centos离线安装gcc 1. gcc是什么? GCC(GNU Compiler Collection)是 GNU 项目下的开源编译器套件,主要用于将 C、C 等编程语言的源…...
odbus TCP转Modbus RTU网关快速配置案例
Modbus TCP 转Modbus RTU网关快速配置案例 在工业自动化领域,Modbus 协议以其简洁和高效而著称,成为众多设备通信的首选。 随着技术的发展和应用场景的变化,Modbus 协议也发展出了不同的版本,其中 Modbus TCP 和 Modbus RTU 是两种…...
Unity3D开发AI桌面精灵/宠物系列 【一】 窗口透明化 背景剔除 、去边框、去Logo动画UI正常显示
Unity3D 交互式AI桌面宠物开发系列【一】 文章主要介绍怎么制作AI桌面宠物的流程,我会从项目开始创建初期到最终可以和AI宠物进行交互为止,项目已经开发完成,我会仔细梳理一下流程,分步讲解。 这篇文章主要讲初期一些设置和部署。…...
Vue 自定义指令深度解析与应用实践
文章目录 1. 自定义指令概述1.1 核心概念1.2 指令生命周期 2. 自定义指令基础2.1 指令注册2.2 指令使用 3. 指令钩子函数详解3.1 钩子函数参数3.2 钩子函数示例 4. 自定义指令应用场景4.1 表单自动聚焦4.2 权限控制4.3 图片懒加载 5. 高级应用技巧5.1 动态指令参数5.2 指令修饰…...
基于SpringBoot+Vue的幼儿园管理系统+LW示例参考
1.项目介绍 系统角色:管理员、教师、普通用户功能模块:用户管理、教师管理、班级管理、幼儿信息管理、会议记录管理、待办事项、职工考核、请假信息、缴费信息、体检管理、资源管理、原料管理、菜品信息管理等技术选型:SpringBoot࿰…...