C++中多态的原理【精华】
虚函数表
通过一道题我们先感受一下编译器针对多态的处理
#include <iostream>
using namespace std;class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
private:int _b = 1;char _c
};int main()
{cout << sizeof(Base) << endl;return 0;
}
在x64环境下,显示的结果是12字节

为什么是12字节呢?一个int就4字节,一个char就1字节,内存对齐一下也是8字节呀!为什么显示的结果是12字节呢? 我们调试代码,看看内部结构

通过调试我们发现Base创建的对象里面有一个指针_vfptr,如果我们计算sizeof的时候把这个指针算上的话刚刚好的12字节!
那么疑问来了,这个指针到底是什么?为什么会出现在对象里面?这个指针到底有什么作用?
这个指针我们叫做虚函数表指针(v代表virtual,f代表function)。一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也简称虚表,。那么子类中这个表放了些什么呢?我们接着往下分析
#include <iostream>
using namespace std;class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}virtual void Func2(){cout << "Func2()" << endl;}void Func3(){cout << "Func3()" << endl;}
private:int _b = 1;char _c;
};int main()
{cout << sizeof(Base) << endl;Base b;return 0;
}
通过监视窗口再来看:

我们发现这个指针指向一个数组(虚函数表),这个数组(表)里面存的就是虚函数的地址
知道了包含虚函数的类里面会出现一个指针,这个指针指向一个指针数组,数组里面保存的是类里面的虚函数,接下来我们看看多态的原理
文章目录
- 虚函数表
- 多态的原理
多态的原理
提示:这里可以添加本文要记录的大概内容:
class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }virtual void func(){}
private:int _a = 1;
};class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
private:int _b = 0;
};void Func(Person& p)
{p.BuyTicket();
}int main()
{Person p;Student s;Func(p);Func(s);return 0;
}
我们看一下父类的虚表指针

我们看到Person对象里面的_vfptr指向的指针数组里面有两个指针,说明保存的是两个地址,我们看看这两个地址是什么?

然后我们看一下_vfptr指针指向的数组里面保存的地址

再看一下子类的虚表指针

虚函数需要被重写,一开始子类会将虚函数进行直接拷贝,重写虚函数之后,虚函数的地址就发生改变了
那为什么多态的原理和指向的对象有关?和虚表有什么关系?

父类对象找到虚函数表的地址,在表里面找到虚函数的地址,因为这里是父类对象,直接调用父类对象的虚函数
子类对象赋值给父类对象,这样会产生“切片”,找到子类中父类的那一部分,寻找到虚函数表的地址,但是虚函数表里存的是子类重写的父类虚函数的地址,所以此时_vfptr指向的其实是子类的虚函数指针数组,自认而然掉用的是子类的虚函数
那为什么不使用指针和引用后,就不构成多态了呢?
#include <iostream>
#include <string>
#include <vector>
using namespace std;class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }virtual void func() {}
private:int _a = 1;
};class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
private:int _b = 0;
};void Func(Person p)
{p.BuyTicket();
}int main()
{Person p;Student s;Func(p);Func(s);return 0;
}

因为指针和引用是指向子类对象切割出来的父类对象的那一部分
不使用指针和引用后,直接将子类传递给父类,切割出来的子类对象中父类的那一部分,成员拷贝给父类,但是不会拷贝虚表指针
相关文章:
C++中多态的原理【精华】
虚函数表 通过一道题我们先感受一下编译器针对多态的处理 #include <iostream> using namespace std;class Base { public:virtual void Func1(){cout << "Func1()" << endl;} private:int _b 1;char _c };int main() {cout << sizeof(B…...
亿赛通电子文档安全管理系统 Update.jsp SQL注入
目录 0x01 漏洞介绍 0x02 影响产品 0x03 语法特征 0x04 漏洞复现页面 0x05 漏洞修复建议 0x01 漏洞介绍 亿赛通电子文档安全管理系统是国内最早基于文件过滤驱动技术的文档加解密产品之一,保护范围涵盖终端电脑(Windows、Mac、Linux系统平台&#…...
神经网络中的反向传播:综合指南
塔曼纳 一、说明 反向传播是人工神经网络 (ANN) 中用于训练深度学习模型的流行算法。它是一种监督学习技术,用于调整网络中神经元的权重,以最小化预测输出和实际输出之间的误差。 在神经网络中,反向传播是计算损失函数…...
协同创新、奔赴未来——“华为云杯”2023人工智能创新应用大赛华丽谢幕
9月27日,在苏州工业园区管理委员会、华为云计算技术有限公司的指导下,由SISPARK(苏州国际科技园)、华为(苏州)人工智能创新中心联合主办,东北大学工业智能与系统优化国家级前沿科学中心、浙江大…...
介绍Node.js中fs模块 代码和注释。
Node.js中的fs模块提供了一些用于文件系统操作的API,包括文件读写、目录操作等。 读取文件 使用fs.readFile()方法可以读取文件内容。该方法的第一个参数是文件路径,第二个参数是可选的选项对象,第三个参数是回调函数。回调函数的第一个参数…...
【QT 读取JSON】 深入浅出 使用QT内置的QJson模块解析Json文件 匠心之作
目录 0 引言1 Json数据分析2 解析Json数据 🙋♂️ 作者:海码007📜 专栏:QT专栏💥 标题:【QT 读取JSON】 使用QT内置的QJson模块解析Json文件❣️ 寄语:人生的意义或许可以发挥自己全部的潜力&…...
初识javaweb2 tomcat
如果是tomcat启动成功却无法通过localhost:8080进入页面,先去查看是否是端口号被占用, 再用命令中断占用的进程,如果简单的命令窗口无法中断,切换到管理员身份运行即可 netstat -ano|findstr "8080" 查看那个进程占用了…...
使用OPENROWSET :在一个数据库中查询另一个数据库的数据
当你需要在一个数据库中查询另一个数据库的数据时,SQL Server提供了多种方法来实现这一目标。一种常见的方法是使用链接服务器(Linked Server),另一种方法是使用 OPENROWSET 函数。本篇博客将重点介绍如何使用 OPENROWSET 函数在当…...
基于STM32设计的智慧农业管理系统(ESP8266+腾讯云微信小程序)
一、项目介绍 基于STM32设计的智慧农业控制系统(ESP8266+腾讯云微信小程序) 1.1 项目背景 随着人们对食品安全和生态环境的日益重视,智慧农业逐渐成为一个备受关注的领域。智能化管理可以提高农业生产效率,减少资源浪费,改善生态环境。因此,基于物联网技术的智慧农业管理系…...
Flutter视图原理之三棵树的建立过程
目录 三棵树的关系树的构建过程1.updateChild函数(element的复用)2.inflateWidget函数3.mount函数3.1 componentElement的实现3.2 RenderObjectElement的实现3.2.1 attachRenderObject函数 4.performRebuild函数 总结三棵树创建流程 三棵树的关系 Flutt…...
详细解析冒泡排序,JS如何基本实现的。
目录 冒泡排序是什么: 使用冒泡排序是为了什么: DEMO示例: 冒泡排序是什么: 冒泡排序(Bubble Sort)是一种简单的比较排序算法,它通过多次遍历待排序的元素,比较相邻元素的大小,如果它们的顺序不正确就交换它们&…...
如何消除CSDN博文代码中自动添加的行号
哪里有自定义目录标题 编写CSDN博文,使用代码块的linux命令行,预览时没有代码行号,但发布文章后自动添加了行号。 git clone https://github.com/mikel-brostrom/yolo_tracking.git cd yolo_tracking pip install -v -e .为什么预览和发布的…...
定制效果在线定制印刷系统源码 DIY在线定制系统源码 云印刷定制系统源码手机、PC端实时互通
支持各类产品的在线定制,无论是水杯雨伞U盘还是T恤衬衫四件套,均可轻松进行定制 独创制作间概念,同一套模板可以重复对应不同制作间 手机、PC端实时互通,客户可通过任意途径进行图片上传、编辑,一方修改另一方即时可见…...
算法|每日一题|同积元组|哈希统计
1726.同积元组 原题地址: 力扣每日一题:同积元组 给你一个由 不同 正整数组成的数组 nums ,请你返回满足 a * b c * d 的元组 (a, b, c, d) 的数量。其中 a、b、c 和 d 都是 nums 中的元素,且 a ! b ! c ! d 。 class Solution …...
最新AI创作系统ChatGPT网站H5源码V2.6.4+搭建部署教程+支持GPT4.0+支持ai绘画(Midjourney)/支持Prompt预设应用
一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统AI绘画系统,支持OpenAI GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署…...
最新!两步 永久禁止谷歌浏览器 Google Chrome 自动更新
先放效果图: CSDN这个问题最火的大哥的用了没用 像他这样连浏览器都打不开 为什么要禁止chrome自动更新 看到很多搞笑的大哥,说为啥要禁止; 我觉得最大的原因就是chromedriver跟不上chrome的自动更新,导致我们做selenium爬虫的…...
在Java中线程和进程的区别
在Java中,线程和进程的区别与一般的操作系统环境下类似,但在Java语言层面上也有一些特点。下面是在Java中线程和进程的区别: 定义:在Java中,进程是指一个正在运行的应用程序实例,而线程是进程中的执行单元。…...
【高危安全通告】Oracle 10月月度安全漏洞预警
近日,安全狗应急响应中心关注到Oracle官方发布安全公告,共披露出在Oracle Weblogic中存在的6个高危漏洞。 漏洞描述 CVE-2023-22069:Oracle Weblogic 远程代码执行漏洞 Oracle WebLogic Server存在远程代码执行漏洞,该漏洞的CVS…...
卷王问卷考试系统SurveyKing,开源调查问卷和考试系统源码
卷王问卷考试系统/SurveyKing是一个功能最强大的开源调查问卷和考试系统,可以快速部署,并适用于各行业。该系统提供了在线表单设计、数据收集、统计和分析等功能,支持20多种题型,多种创建问卷方式和多种问卷设置。 无论您是需要进…...
uniapp开发微信小程序,webview内嵌h5,h5打开pdf地址,解决方案
根据公司要求,让我写一个h5,后续会嵌入到合作公司的微信小程序的webview中,如果是自己公司微信小程序,可以采取先下载下来pdf,然后通过wx.openDocument,进行单纯的预览操作,这个可以根据这个老哥…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
