C++多态原理

C++多态原理

  • 多态的原理
  • 动态绑定与静态绑定
    • 静态多态
    • 动态多态
  • 虚函数存在哪的?虚表存在哪的?

多态的原理

// 这里常考一道笔试题:sizeof(Base)是多少?
class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
private:int _b = 1;
};

在这里插入图片描述
通过观察测试我们发现b对象是8bytes,除了_b成员,还多一个_vfptr放在对象的前面(注意有些平台可能会放到对象的最后面,这个跟平台有关),对象中的这个指针我们叫做虚函数表指针(v代表virtual,f代表function)。

在这里插入图片描述
虚函数表指针,在32位下是四个字节,64位下是八个字节,这个指针会指向一张表,这个表叫虚函数表,虚函数表本质是一个指针数组。

一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也简称虚表。

函数编译好了之后都是一串指令,这些指令都是放到代码段里,所以,虚函数并不是放到虚表里,而是把虚函数的地址放到虚表里,函数的地址就是编译完后的第一条指令的地址。

class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}virtual void Func2(){cout << "Func2()" << endl;}void Func3(){cout << "Func3()" << endl;}
private:int _b = 1;
};

在这里插入图片描述

因为,Fun1函数Func2函数是虚函数,所以Fun1函数Func2函数的地址会放到虚表里面。Func3不是虚函数,F所以un3函数的地址没有放到虚表里面。

在这里插入图片描述

虚函数表本质是一个存虚函数指针的指针数组,一般情况这个数组最后面放了一个nullptr。

动态绑定与静态绑定

  1. 静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态,比如:函数重载
  2. 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态。
class Base
{
public:virtual void Func1(){cout << "Base::Func1()" << endl;}virtual void Func2(){cout << "Base::Func2()" << endl;}void Func3(){cout << "Base::Func3()" << endl;}
private:int _b = 1;
};class Derive : public Base
{
public:virtual void Func1(){cout << "Derive::Func1()" << endl;}
private:int _d = 2;
};void Func1(Base* p)
{//动态绑定/运行时绑定	//运行的时候确定函数的地址,通过指向对象的虚指针找到函数的地址p->Func1();//静态绑定/编译时绑定//普通函数在编译时就能确定函数的地址,跟指向的对象没有关系p->Func3();
}

在这里插入图片描述

可以看到对于Func1函数传一个Base对象的指针调用的就是Base的Fun1函数,传一个Derive对象的指针调用的就是Deirve的Fun1函数,但是对于Func3函数传入的无论是Base对象的指针还是Derive对象的指针调用的都是Base的指针。

那这里是怎么实现的呢?通过调试窗口可以看到

在这里插入图片描述
在这里插入图片描述

可以观察到基类b对象和派生类d对象虚表是不一样的,这样可以避免混淆,这里我们发现Func1完成了重写,所以d的虚表中存的是重写的Derive::Func1,所以虚函数的重写也叫作覆盖,覆盖就是指虚表中虚函数的覆盖。重写是语法的叫法,覆盖是原理层的叫法。

另外Func2继承下来后是虚函数,所以放进了虚表,因为虚函数Func2并没有完成重写所以,两个虚表中,Func2函数的地址是一样的,Func3也继承下来了,但是不是虚函数,所以不会放进虚表。

派生类的虚表生成:

  1. 先将基类中的虚表内容拷贝一份到派生类虚表中
  2. 如果派生类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数
  3. 派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。

静态多态

int main()
{int i = 0;double d = 1.1;//给不同的类型实现不同的效果//通过运算符重载,在编译的时候就确定了cout << i;cout << d;int a = 1, b = 2;char x = 'x', y = 'y';//通过函数模板,不同参数实例化不同的函数//在编译时通过不同的参数就实例化出不同函数swap(a, b);swap(x, y);}

动态多态

在运行时去虚表里面去找,实现运行的多种形态,根据指向的对象不同,达到不同的效果。

虚函数存在哪的?虚表存在哪的?

虚函数和普通函数一样的,都是存在代码段的,只是他的指针又存到了虚表中。另外对象中存的不是虚表,存的是虚表指针。虚表的指针是存在对象里面的,那么虚表存在那的呢?

下面是一个测试。

int main()
{int i = 0;static int j = 1;int* p1 = new int;const char* p2 = "xxxxx";printf("栈:%p\n", &i);printf("静态区:%p\n", &j);printf("堆:%p\n", p1);printf("常量区:%p\n", p2);Base b;Derive d;printf("Base虚表地址:%p\n", *(int*)&b);printf("Deirve虚表地址:%p\n", *(int*)&d);
}

在这里插入图片描述
所以,可以看到虚表与常量区更接近一点,所以虚表一般存在常量区,或者代码段。

同一个类型的对象,虚表是一样的,共享一张虚表。

一个题目

多继承中指针偏移问题?下面说法正确的是( )

class Base1 {  public:  int _b1; };
class Base2 {  public:  int _b2; };
class Derive : public Base1, public Base2 { public: int _d; };
int main(){Derive d;Base1* p1 = &d;Base2* p2 = &d;Derive* p3 = &d;return 0;
}

A:p1 == p2 == p3 B:p1 < p2 < p3 C:p1 == p3 != p2 D:p1 != p2 != p3

对象模型就是说,编译器通过编译后,编译器生成这个对象,这个对象里的各个变量的是通过成员变量声明顺序分布的,先声明的在前面,对于继承的类来说,先继承的基类成员在派生类对象的内存布局的前面。
在这里插入图片描述

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

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

相关文章

【单调栈】单调栈基础及经典案例

【单调栈】单调栈基础及经典案例 单调栈理论基础每日温度下一个更大元素Ⅰ下一个更大元素Ⅱ经典例题—接雨水思路一 暴力求解思路二 双指针优化思路三 单调栈解法 经典例题—柱状图中最大的矩形思路一 暴力求解思路二 单调栈 单调栈理论基础 单调栈的应用场景&#xff1a;要寻…

109.游戏安全项目:信息显示二-利用游戏通知辅助计算基址

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;易道云信息技术研究院 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要盲目相信…

Visual Studio使用与“Hello Word“的编写

1.打开Visual Studio点击"创建新项目" 2.点击"空项目"&#xff0c;并点击"下一步" 3.设置"项目名称"并"设置地址" 4.打开项目后&#xff0c;右击"源文件"并选择"添加"的"新建项" 5.点击"…

Java每日面试题(JVM)(day15)

目录 Java对象内存布局markWord 数据结构JDK1.8 JVM 内存结构JDK1.8堆内存结构GC垃圾回收如何发现垃圾如何回收垃圾 JVM调优参数 Java对象内存布局 markWord 数据结构 JDK1.8 JVM 内存结构 程序计数器: 线程私有&#xff0c;记录代码执行的位置. Java虚拟机栈: 线程私有&#…

【移植】标准系统方案之扬帆移植案例

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 本文章是基于瑞芯微RK3399芯片的yangfan开发板&#xff0c;进行标准…

【论文速看】DL最新进展20240927-目标检测、Transformer

目录 【目标检测】【Transformer】 【目标检测】 [2024小目标检测] A DeNoising FPN With Transformer R-CNN for Tiny Object Detection 论文链接&#xff1a;https://arxiv.org/abs/2406.05755 代码链接&#xff1a;https://github.com/hoiliu-0801/DNTR 尽管计算机视觉领域…

笔记整理—linux进程部分(1)进程终止函数注册、进程环境、进程虚拟地址

对于mian()函数而言&#xff0c;执行前也需要先执行一段引导代码才会去执行main()函数&#xff0c;该部分的代码包含构建c语言的运行环境等配置&#xff0c;如清理bss段等。 在使用gcc去编译程序的时候&#xff0c;使用gcc -v xxx.c可见链接过程。在编译完成后可见xxx.out文件。…

数据结构——计数、桶、基数排序

目录 引言 计数排序 1.算法思想 2.算法步骤 3.代码实现 4.复杂度分析 桶排序 1.算法思想 2.算法步骤 3.代码实现 4.复杂度分析 基数排序 1.算法思想 2.算法步骤 3.代码实现 4.复杂度分析 排序算法的稳定性 1.稳定性的概念 2.各个排序算法的稳定性 结束语 引…

NVLM多模态 LLM 在图像和语言任务中的表现优于 GPT-4o

论文地址&#xff1a;https://arxiv.org/pdf/2409.11402 背景 传统的多模态 LLM 有两种主要方法&#xff1a;纯解码器架构&#xff08;如 LLaVA&#xff09;和基于交叉注意力的架构&#xff08;如 Flamingo&#xff09;。混合架构&#xff0c;既提高了训练效率&#xff0c;又增…

[CKA]CKA的购买和注册考试券

CKA的购买和注册考试券 一、购买CKA 1、注册 LF开源软件学园 账号 LF开源软件学园&#xff1a;https://training.linuxfoundation.cn/register 2、个人中心进行实名认证 3、按需求进行购买 4、在考试中心–我的订单 中查看购买的订单 我是在"黑色星期五"打折买的…

LLM大模型书籍:专补大模型短板的RAG入门与实战书来了!

文末赠书 RAG自2020年由Facebook AI Research推出后&#xff0c;一下子就窜红了。 毕竟&#xff0c;它是真的帮了大忙&#xff0c;在解决大语言模型的“幻觉”问题上起到了关键作用。 如今&#xff0c;Google、AWS、IBM、微软、NVIDIA等科技巨头都在支持RAG应用的开发。微软…

中国新媒体联盟与中运律师事务所 建立战略合作伙伴关系

2024年9月27日&#xff0c;中国新媒体联盟与中运律师事务所举行战略合作协议签字仪式。中国新媒体联盟主任兼中国社会新闻网主编、中法新闻法制网运营中心主任左新发&#xff0c;中运律师事务所高级顾问刘学伟代表双方单位签字。 中国新媒体联盟是由央视微电影中文频道联合多家…

你的下一台手机会是眼镜吗?RTE 大会与你一同寻找下一代计算平台丨「空间计算和新硬件」论坛报名

周四 Meta 刚公布新一代 AR 眼镜 Orion 后&#xff0c;Perplexity 的 CEO 发了一条状态&#xff1a;「如果你还在做软件&#xff0c;请转型硬件。」 一家估值 30 亿美元的 AI 软件公司 CEO 说出这样的言论&#xff0c;既有有见到「最强 AR 眼镜」Orion 后的激动情绪&#xff0c…

如何组织一场考试并筛选未参加答题的考生?

&#x1f64b;频繁有小伙伴咨询&#xff1a;我组织了一场答题活动&#xff0c;导出考试成绩时只有参加了答题的人&#xff0c;但我想要找到哪些人没答题 此前我们会建议小伙伴逐人排查&#xff0c;但这建议被反复吐槽&#x1f926; 确实&#xff0c;如果只有十几个人逐人排查还…

鸿蒙开发(NEXT/API 12)【硬件(Pen Kit)】手写笔服务

Pen Kit&#xff08;手写笔服务&#xff09;是华为提供的一套手写套件&#xff0c;提供笔刷效果、笔迹编辑、报点预测、一笔成形和全局取色的功能。手写笔服务可以为产品带来优质手写体验&#xff0c;为您创造更多的手写应用场景。 目前Pen Kit提供了四种能力&#xff1a;手写…

银行大模型,走到哪了?

频道说 透过近期披露的上市银行中报&#xff0c;窥探银行业大模型最新进展。 大模型浪潮依然汹涌澎湃。 9月12日&#xff0c;OpenAI全新发布o1模型&#xff0c;在复杂推理任务取得重大进步&#xff0c;代表了人工智能能力的新水平&#xff0c;被视为AI时代的又一个里程碑。 …

Bigemap Pro首发(一款真正全面替代Arcgis的国产基础软件)

Bigemap Pro是一款功能强大的计算机数据要素辅助设计(Computer-Aided Data Elements Design CADED)软件&#xff0c;由成都比格图数据处理有限公司研发设计&#xff0c;主要应用在数据要素设计领域&#xff0c;为各行业提供安全可靠高效易用的数据要素设计类国产化基础软件。Bi…

公交换乘C++

题目&#xff1a; 样例解释&#xff1a; 样例#1&#xff1a; 第一条记录&#xff0c;在第 3 分钟花费 10 元乘坐地铁。 第二条记录&#xff0c;在第 46 分钟乘坐公交车&#xff0c;可以使用第一条记录中乘坐地铁获得的优惠票&#xff0c;因此没有花费。 第三条记录&#xff0c;…

OpenCV与AI深度学习 | 实战 | 使用OpenCV和Streamlit搭建虚拟化妆应用程序(附源码)

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;实战 | 使用OpenCV和Streamlit搭建虚拟化妆应用程序&#xff08;附源码&#xff09; 现看看demo演示。 本文将介绍如何使用Streamlit和OpenCV…