多态深度剖析
前言
继承是多态的基础,
如果对于继承的知识还不够了解,
可以去阅读上一篇文章
继承深度剖析
基本概念与定义
概念:
通俗来说,就是多种形态。具体点就是去完成某个行为,
当不同的对象去完成时会产生出不同的状态。
举个栗子:
比如买票这个行为,当普通人买票时,是全价买票;
学生买票时,是半价买票;
军人买票时是优先买票。
构成多态的两个必要条件:
1. 必须通过基类的指针或者引用调用虚函数
2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
那么,什么是虚函数?什么是重写?
将virtual关键字加在成员函数前面,这个函数就是虚函数

虚函数的重写(覆盖)
派生类中有一个除函数内部跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称派生类的虚函数重写了基类的虚函数
class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
};
实例
使用多态时,切记要注意构成多态的两个必要条件
实例
class Person
{
public:virtual void Buy(){cout << "全价" << endl;}
};class student :public Person
{
public:virtual void Buy(){cout << "半价" << endl;}
};int main()
{Person p;student s;p.Buy();s.Buy();return 0;
}
运行结果

p是基类Person的实例,s是派生类Student的实例。当
p调用Buy函数时,它调用的是Person类中的函数,因此输出 “全价”。而当
s调用Buy函数时,它调用的是
Student类中的重写函数,因此输出 “半价”。通过重写基类中的虚函数,派生类可以改变函数的行为,这就是多态性。
尽管
p和s都调用了Buy函数,但由于它们所属的类不同,输出的结果也不同。
构成多态的两个特例
1.派生类虚函数不写virtual关键字依旧构成多态

2.基类与派生类虚函数返回值类型不同
也可以构成多态(返回值必须满足某种条件)

基类的返回值要返回基类
派生类的返回值要返回派生类
注意
1.父类不写virtual,而子类的同名
函数写了virtual,这是不构成多态的!
class Person
{
public:void Buy(){}
};class student :public Person
{
public:virtual void Buy(){}
};
2.在继承体系中,父子类的同名
函数不构成重写就构成隐藏,不可能构成重载!
底层原理分析

大家先思考一下这套题目的答案,
如果你单纯的认为Base类只有一个
整型变量占用空间,答案是4的话,那你就上当啦!
事实上在32位机器下,这里的结果是8
在64位机器下,这里的结果是16!
32

64

因为它除了有一个变量外,还有一个指针,此指针指向一个虚函数表
使用这一段代码观察
class A
{
public:virtual void func1(){cout << "父类func1";}
private:int _a;
};
class B : public A
{
public:virtual void func1(){cout << "子类func1";}
private:int _b;
};int main()
{A a;B b;return 0;
}

此指针叫虚表指针:vfptr,也就是virtual function ptr
这个指针并不是直接指向虚函数的地址
而是指向一个虚函数表,可以理解位一个
数组,此数组中存放着此对象中所有的虚
函数的地址,它们的关系可以用下图表示:

注:不管有没有继承体系或多态只要有虚函数就有虚表!
那么父类和子类的虚表指针和指向
的内容有什么不同或相同处吗?
形成多态现象的原理又是什么?
class A
{
public:virtual void func1()cout << "父类func1";virtual void func2()cout << "父类func2";
private:int _a;
};
class B : public A
{
public:virtual void func1()cout << "子类func1";
private:int _b;
};
int main()
{A a;B b;return 0;
}

这证明:
父类和子类的虚表指针是不同的
证明父子类各有一张虚函数表!
函数func1在子类中被重写了,所以
父子类虚表中的func1函数地址是不同的
函数func2没有被子类重写,所以
父子类虚表中的func2函数地址是相同的
结论:同一个类的不同对象共用一个虚表
多态的原理深度剖析:
当一个函数A被重写时,它的父类虚表存放
父类函数A的地址,子类虚表存放的是子类
函数A的地址!
当父类的指针或引用指向子类空间时
调用虚函数时,会到指向对象的虚表中
中找到对应的虚函数地址,进行调用!
父子类都只有A函数或无函数时
-
若父类写了虚函数A,而子类
甚至没有写函数A,此时子类对象中
存储的虚函数地址与父类相同 -
若父类甚至没有写函数A,而子类
直接写了虚函数A,则父类对象中没有
虚表,而子类对象中有虚表(存放A)
多态中的两个关键字
final:修饰虚函数,表示该虚函数不能被重写

override:检查子类类虚函数是否重写了
基类虚函数如果没有被重写则编译报错

抽象类以及虚函数的几个结论
抽象类概念:
在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写
抽象类的只需了解即可,实际中使用到的场景很少
其他结论
1.内联函数可以是虚函数吗?
可以,如果是普通调用,内联起作用,如果是多态调用,内联不起作用。
2.静态成员可以是虚函数吗?
不可以,编译会报错,静态成员函数没有this指针,可以指定类域调用,无法构成多态。
3.构造函数可以是虚函数吗?
不可以,编译会报错,对象中的虚表指针是构造函数阶段时才初始化的,虚函数多态调用,要到虚表中找,但是此时虚表指针还未初始化。
4.析构函数可以是虚函数吗?
最好是虚函数。
5.访问普通函数快还是访问虚函数快?
普通调用时是一样快的,多态调用时会慢一点,以为要去虚表中查找。
6.虚函数表在什么阶段形成,存在哪里?
虚函数表在编译阶段就形成了,虚函数表指针构造时才初始化给对象,存储在代码段中。
7.动态多态与静态多态
静态多态多指函数重载,运算符重载;
动态多态就是本章的内容了,
条件:1.父类的引用或指针调用虚函数。
2.虚函数完成重写指向谁,调用谁,实现多种形态
相关文章:
多态深度剖析
前言 继承是多态的基础, 如果对于继承的知识还不够了解, 可以去阅读上一篇文章 继承深度剖析 基本概念与定义 概念: 通俗来说,就是多种形态。具体点就是去完成某个行为, 当不同的对象去完成时会产生出不同的状…...
OSPF被动接口配置(华为)
#交换设备 OSPF被动接口配置 一、基本概念 OSPF被动接口,也称为抑制接口,即将路由器某一接口配置为被动接口后,该接口不会再接受和发送OSPF报文 二、使用场景 在路由器与终端相近或者直接相连的一侧配置被动接口 因为OSPF会定期发送报文…...
Android --- 异步操作
同步和异步的差异 同步:在发生某件事后什么也不做,直到该事件完成后,再继续进行 异步:在某件事发生后,可以在等待他完成的时候去处理其他事件,等到该事件发生完成后,再回过头来处理它。 异步…...
(55)MOS管专题--->(10)MOS管的封装
(10)MOS管的封装 1 目录 (a)IC简介 (b)数字IC设计流程 (c)Verilog简介 (d)MOS管的封装 (e)结束 1 IC简介 (a)在IC设计中,设计师使用电路设计工具(如EDA软件)来设计和模拟各种电路,例如逻辑电路、模拟电路、数字信号处理电路等。然后,根据设计电路的…...
超高清图像生成新SOTA!清华唐杰教授团队提出Inf-DiT:生成4096图像比UNet节省5倍内存。
清华大学唐杰教授团队最近在生成超高清图像方面的新工作:Inf-DiT,通过提出一种单向块注意力机制,能够在推理过程中自适应调整内存开销并处理全局依赖关系。基于此模块,该模型采用了 DiT 结构进行上采样,并开发了一种能…...
网络安全 - DNS劫持原理 + 实验
DNS 劫持 什么是 DNS 为什么需要 DNS D N S \color{cyan}{DNS} DNS(Domain Name System)即域名系统。我们常说的 DNS 是域名解析协议。 DNS 协议提供域名到 IP 地址之间的解析服务。计算机既可以被赋予 IP 地址,也可以被赋予主机名和域名。用…...
MyBatis的运行原理
目录 1、目的:梳理一下MyBatis运行时的几个对象,我们需要搞清楚他们的作用,进而需要理解mybatis的整个工作流程和执行原理。 2、简要概括各个类 2.1 Resources 作用:编写资源加载类,使用类加载器加载 配置文件(myb…...
算法题解记录29+++全排列(百日筑基)
一、题目描述 题目难度:中等 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 示…...
苹果AI功能,AI训练数据缺乏,SD3推出,MJ6推出新特性
更多信息: https://agifun.love 智源社区 2024智源大会议程公开丨大模型前沿探索 2024年6月14日-15日,第6届北京智源大会将以线下与线上结合的形式召开,线下会场设在中关村国家自主创新示范区会议中心。2024智源大会再次以全球视野&#x…...
超越中心化:Web3如何塑造未来数字生态
随着技术的不断发展,人们对于网络和数字生态的期望也在不断提升。传统的中心化互联网模式虽然带来了便利,但也暴露出了诸多问题,比如数据滥用、信息泄露、权力集中等。在这样的背景下,Web3技术应运而生,旨在打破传统中…...
【ic-tool】timegen使用
一、前言 TimeGen是一个用于时序波形编辑的CAD工具,它允许数字设计工程师快速有效地绘制数字时序图。TimeGen时序图可以很容易地导出到其他窗口程序,如microsoftword,用于编写设计规范。可直接从官网下载TimeGEN软件:TimeGen Pro…...
1:25万基础电子地图(云南版)
我们在《50幅1:25万基础电子地图(四川版)》一文中,为你分享过四川的50幅基础电子地图。 现在我们再为你分享云南的1:25万基础电子地图,你可以在文末查看该数据的领取方法。 基础电子地图云南版 下载后可以看到该数据…...
springboot宠物领养系统-计算机毕业设计源码07863
摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存…...
牛客热题:最长回文子串
📟作者主页:慢热的陕西人 🌴专栏链接:力扣刷题日记 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 文章目录 牛客热题:最长回文子串题目链接方法一&am…...
如何访问寄存器
标题 方式一:对地址进行宏定义方式二:用结构体封装寄存器 访问寄存器是CPU执行程序的基础,每种CPU架构都有其特定的寄存器集合和访问方式。 方式一:对地址进行宏定义 #define GPIOA_BASE ((unsigned int)0x48000000) #define GPI…...
苍穹外卖笔记-18-修改密码、bug记录
文章目录 1 修改密码1.1 需求分析和设计1.2 代码实现1.2.1 admin/EmployeeController1.2.2 EmployeeService1.2.3 EmployeeServiceImpl 1.3 功能测试 2 bug记录 1 修改密码 完结的时候发现还有一个接口未实现。这里补充 1.1 需求分析和设计 产品原型: 业务规则&am…...
java如何截取字符串
如果想在一个字符串中截取一段字符,形成新的字符,那么在java中途需要用到substring语句 substring的语法格式是 str.substring(beginindex,endindex) 其中str是字符串 beginindex是起始索引,endindex是结束索引 截取的字符串包含起始索引…...
虚拟淘宝-Virtual-Taobao论文解读(AAAI2019)
目录 1 论文简介 2 文章的主要贡献 3 文章技术的简要说明 4 技术的详细说明 4.1 GAN-SD:生成客户特征 4.2 MAIL:生成交互过程 4.3 ANC:动规范约束 5 实验设定及结果 6 结论 7 参考 1 论文简介 南京大学LAMDA团队的侍竞成、俞扬等…...
低代码组件扩展方案在复杂业务场景下的设计与实践
组件是爱速搭的前端页面可视化模块的核心能力之一,它将前端研发人员从无休止的页面样式微调和分辨率兼容工作中解放了出来。 目前,爱速搭通过内置的上百种功能组件(120),基本可以覆盖大部分中后台页面的可视化设计场景…...
震撼科技界的GPT-4o发布首日即遭“越狱破防”
前言 本文主要解读分析OpenAI最新推出的大型模型GPT-4o可能存在的越狱风险。 5 月14 日凌晨的科技圈再一次被OpenAI轰动,其发布的最新大模型GPT-4o,能力横跨语音、文本和视觉,这一成果无疑再次巩固了OpenAI在人工智能领域的领先地位。 然而…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
