C++ 多态:概念,定义及实现以及原理
目录一.多态的概念1.1静多态1.2动多态重点二.多态的定义及实现2.1 多态的构成条件2.1.1 虚函数2.1.2 实现多态还有两个必须重要条件2.1.3 虚函数的重写/覆盖2.1.4 多态场景的一个选择题腾讯面试题2.1.5 虚函数重写的一些其他问题2.1.6override和final关键字2.1.7重载/重写/隐藏的对比面试考点一.多态的概念多态polymorphism的概念通俗来说就是多种形态。多态分为编译时多态静态多态和运行时多态动态多态这里我们重点讲运行时多态编译时多态静态多态和运行时多态动态多态。编译时多态静态多态主要就是我前面文章讲的函数重载和函数模板他们传不同类型的参数就可以调用不同的函数通过参数不同达到多种形态之所以叫编译时多态是因为他们实参传给形参的参数匹配是在编译时完成的我们把编译时一般归为静态运行时归为动态。运行时多态具体点就是去完成某个行为函数可以传不同的对象就会完成不同的行为就达到多种形态。比如买票这个行为当普通人买票时是全价买票学生买票时是优惠买票5折或75折)军人买票时是优先买票。再比如同样是动物叫的一个行为函数传猫对象过去就是”( ^ w ^ 喵“传狗对象过去就是”汪汪”。1.1静多态1. 核心定义在代码编译阶段编译器就已经确定好了要执行哪一个函数地址在编译期绑定也叫静态绑定、早绑定。 程序还没运行调用关系就已经敲定。2. 实现方式函数重载最典型 同一个作用域内函数名一致参数列表个数、类型、顺序不同编译器依靠参数区分调用哪个函数。运算符重载C3. 特点绑定时机编译期执行效率高运行时无额外开销不依赖继承、重写仅依靠函数签名区分。1.2动多态重点1. 核心定义编译阶段无法确定具体调用哪个函数必须等到程序运行起来根据当前对象的真实类型动态匹配对应的函数又称动态绑定、晚绑定。 也是面向对象里大家常说的狭义上的 “多态”。2. 必备条件C/Java 通用逻辑父子类存在继承关系父类声明虚函数C/ 允许重写Java子类重写父类的虚函数使用父类指针 / 引用指向子类对象。3. 特点绑定时机运行期需要继承 重写 虚函数支撑运行时有查表开销效率略低于静态多态同一个调用语句传入不同子类对象表现不同行为是多态最核心价值。对比项静态多态动态多态绑定时机编译期运行期别称早绑定、静态绑定晚绑定、动态绑定实现手段函数重载、运算符重载继承 虚函数重写、父类引用 / 指针是否需要继承不需要必须依靠继承体系运行开销几乎无开销虚表查找轻微运行开销典型场景同一类中同名不同参函数调用统一父类接口不同子类差异化实现二.多态的定义及实现2.1 多态的构成条件多态是一个继承关系的下的类对象去调用同一函数产生了不同的行为。比如Student继承了Person。Person对象买票全价Student对象优惠买票2.1.1 虚函数类成员函数前面加virtual修饰那么这个成员函数被称为虚函数。注意非成员函数不能加virtual修饰注意虚函数和虚继承虽然用的是同一个关键字virtual但是并没有什么关联关系对比维度虚函数 virtual 函数虚继承 virtual 继承修饰对象类的成员函数继承方式父类继承核心目标实现运行时多态动态绑定函数解决菱形多重继承的数据二义性、多份基类副本依赖场景单继承、普通继承都能用仅限多重菱形继承场景底层结构虚函数表 vtable 虚指针 vptr虚基表 虚基指针 vbptr作用对象控制成员函数调用逻辑调整对象内存布局、共享基类成员变量是否影响数据存储不改变成员变量布局大幅改变继承体系的内存布局典型问题解决父类指针精准调用子类重写方法d.A::x分不清是 B 里的 A 还是 C 里的 A内存开销对象增加 1 个 vptr 指针子类增加 vbptr 虚基指针2.1.2 实现多态还有两个必须重要条件被调用的函数必须是虚函数并且完成了虚函数重写/覆盖若父类没有用虚函数则不会构成多态调用的时候只会调用父类基类不开virtual编译时认准指针类型是Animal*固定调用父类方法基类开启virtual运行时查看指针指向的真实对象类型自动匹配子类重写的函数。func(a)→ Animal::talkfunc(c)→ 依然 Animal::talkfunc(d)→ 依然 Animal::talk必须是基类的指针或者引用调用虚函数2.1.3 虚函数的重写/覆盖虚函数的重写/覆盖派生类中有一个跟基类完全相同的虚函数即派生类虚函数与基类虚函数的返回值、函数名字、参数列表完全相同称派生类的虚函数重写了基类的虚函数注意在重写基类虚函数时派生类的虚函数在不加virtual关键字时虽然也可以构成重写因为C 规定基类中被virtual修饰的成员函数其 “虚函数” 的特性会被派生类继承。只要派生类定义的函数与基类虚函数的签名完全一致函数名、参数列表、const/volatile修饰符、返回类型都匹配那么这个派生类函数会自动成为虚函数无需显式加virtual关键字自然也能构成对基类虚函数的重写但是该种写法不是很规范不建议这样使用不过在考试选择题中经常会故意留这个坑让你判断是否构成多态主包之前在腾讯的笔试题中见过非常恶心只能说相关出题人用心险恶。2.1.4 多态场景的一个选择题腾讯面试题代码分析#include iostream using namespace std; // 父类基类A class A { public: // 虚函数func允许子类重写默认参数val1静态绑定的关键 virtual void func(int val 1) { cout A- val endl; } // 虚函数test内部调用func()B未重写此方法继承复用的关键 virtual void test() { func(); // 等价于 this-func()this是隐藏指针 } }; // 子类派生类Bpublic继承A继承的核心 class B : public A { public: // 重写overrideA的虚函数func函数签名和父类一致多态的前提 // 默认参数改为val0但默认参数不参与多态 void func(int val 0) { cout B- val endl; } // 关键B没有重写test() → 完全继承A的test()逻辑 }; int main() { B* p new B; // 静态类型B*动态类型B* p-test(); // 核心调用1重点分析 p-func(); // 核心调用2对比分析 delete p; // 补充避免内存泄漏 return 0; }2.1.5 虚函数重写的一些其他问题协变了解派生类重写基类虚函数时与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指针或者引用派生类虚函数返回派生类对象的指针或引用时称为协变。协变的实际意义并不大所以了解一下即可但是若AB类没有继承关系就会有报错就是因为没有满足协变的要求如下图析构函数的重写笔试常见基类的析构函数为虚函数此时派生类析构函数只要定义无论是否加 virtual 关键字都与基类的析构函数构成重写虽然基类与派生类析构函数名字不同看起来不符合重写的规则实际上编译器对析构函数的名称做了特殊处理编译后析构函数的名称统一处理成 destructor 所以基类的析构函数加了 virtual 修饰派生类的析构函数就构成重写。下面结合代码说明一下某些情况下若析构函数不加 virtual 会出现的问题为什么基类中的析构函数建议设计为虚函数这个问题在面试中经常考察一定要结合样例才可以讲清楚总结基类和派生类的析构函数在编译器的作用下定义为相同的名称在main函数中如果用基类的指针或引用来指向基类或派生类对象时若调用delete则只会调用基类的析构不会调用派生类的析构所以我们要加上virtual来构成多态指向谁调用谁这里为什么调用两次~Person1.Person* p1 new Person; delete p1;真实对象就是Person虚析构触发自身析构函数仅执行~Person()→ 控制台第一行输出~Person()2.Person* p2 new Student; delete p2;因为基类Person析构加了virtual虚析构开启动态绑定完整的析构流程运行时识别真实类型是Student优先调用子类析构~Student()C 语法强制规则子类析构执行完毕后编译器会自动调用直接父类的析构函数不需要手动写代码 → 依次打印~Student()~Person()合在一起三行输出视觉上看到两次~Person()。2.1.6override和final关键字从上面可以看出C对虚函数重写的要求比较严格但是有些情况下由于疏忽比如函数名写错参数写错等导致无法构成重写而这种错误在编译期间是不会报出的只有在程序运行时没有得到预期结果才来debug灰得不偿失因此C11提供了 override 可以帮助用户检测是否重写。如果我们不想让派生类重写这个虚函数那么可以用final修饰一、override关键字1、作用显式声明当前函数意图重写父类的虚函数编译器强制校验 必须确实正确重写了基类的虚函数否则直接编译报错杜绝手误导致 “本该重写实际变成新建重载 / 隐藏函数”。2、使用规则只能写在子类重写虚函数的形参列表末尾只能修饰成员函数不能修饰普通函数、构造 / 析构、变量基类必须是virtual虚函数否则加override编译报错。这里我们可以看出不加override编译器不会报错当我们加上override后直接就会检查出来二.final关键字2.1.7重载/重写/隐藏的对比面试考点

相关新闻

UE Niagara条带渲染器实现动态运动轨迹:从数据驱动到视觉叙事

UE Niagara条带渲染器实现动态运动轨迹:从数据驱动到视觉叙事

1. 项目概述:从静态拖尾到动态轨迹的进化 在游戏和实时视效开发里,给角色添加运动轨迹或拖尾效果,是提升动态表现力和视觉反馈的经典手法。过去,我们可能依赖材质动画、后期处理或者简单的粒子发射器来模拟,但这些方法…

2026/8/7 7:41:26 阅读更多 →
从资质扫描件到 Excel:采购建供应商准入台账的第一步

从资质扫描件到 Excel:采购建供应商准入台账的第一步

采购要把一批资质扫描件整理进 Excel 时,最容易直接跳到“先识别一下”。但真正决定结果能不能交接的,往往是更前面的动作:先说清楚每一列要记录什么、从页面哪里取、看不清时怎么留痕。 所以,建供应商准入台账的第一步不是让扫描…

2026/8/7 7:41:26 阅读更多 →
STM32串口通信实战:从原理到DMA应用与调试技巧

STM32串口通信实战:从原理到DMA应用与调试技巧

1. 项目概述:从零上手STM32串口通信 搞嵌入式开发,尤其是玩STM32的,串口通信绝对是绕不开的第一个“硬骨头”。它不像点个LED灯那么简单,但又是后续所有复杂通信(比如网络、蓝牙)的基础。很多新手&#xff…

2026/8/7 7:41:26 阅读更多 →

最新新闻

天猫改价系统:驱动级硬件伪装,平台检测维度再全也查不出

天猫改价系统:驱动级硬件伪装,平台检测维度再全也查不出

天猫改价系统:驱动级硬件伪装,平台检测维度再全也查不出 每次有人问我店群怎么做大,我就一句话:天猫的极速自动改价,是店群运营中最耗人力也最容易出错的环节。 电商价格战是分钟级的。竞品降价了你5分钟内不跟&…

2026/8/7 8:26:47 阅读更多 →
医院病房护理呼叫 | 解决床位信号卡顿的工业级嵌入式硬件解决方案

医院病房护理呼叫 | 解决床位信号卡顿的工业级嵌入式硬件解决方案

引言 据2025年国内医疗信息化行业调研数据显示,全国三 级医院病房护理呼叫系统覆盖率已达92.7%,但临床运维数据显示,约41%的病区存在床位呼叫信号卡顿、丢包等问题,高峰时段呼叫响应延迟平均可达1.2秒,直接影响护理响…

2026/8/7 8:26:47 阅读更多 →
Windows安装MinGW-w64完整指南:从下载配置到编译测试

Windows安装MinGW-w64完整指南:从下载配置到编译测试

1. 项目概述:为什么我们需要MinGW?如果你刚开始接触C或C编程,尤其是在Windows系统上,可能会被一个词搞懵:MinGW。它不像Visual Studio那样有个漂亮的安装界面,也不像一些集成环境那样开箱即用。但当你需要编…

2026/8/7 8:26:47 阅读更多 →
Unity 2D智能追踪导弹:向量数学与平滑转向实现详解

Unity 2D智能追踪导弹:向量数学与平滑转向实现详解

1. 项目概述:从直线飞弹到智能猎手 在2D射击、塔防或者动作游戏中,一个只会直线前进的飞弹,其威慑力和趣味性都相当有限。玩家和开发者都渴望看到更“聪明”、更具视觉表现力的攻击方式——一枚能够划出优美弧线,像猎犬一样死死咬…

2026/8/7 8:26:47 阅读更多 →
电赛小车开源代码实战:从快速启动到工程化调试与创新

电赛小车开源代码实战:从快速启动到工程化调试与创新

1. 先搞清楚“28秒”到底解决了什么核心问题 看到“28秒摩擦电赛小车题”这种标题,很多人的第一反应是“这么快?怎么做到的?”。但更关键的问题是,这个“快”到底指的是什么?是代码开发快,还是算法调试快&a…

2026/8/7 8:26:47 阅读更多 →
三、AI重塑网络安全攻防格局——冲击、风险与进化路径

三、AI重塑网络安全攻防格局——冲击、风险与进化路径

一、从PromptLock说起 2025年8月,我在刷安全资讯时,被一个名字刺了一下眼睛——PromptLock。这不是某个新发布的AI绘画工具,而是网络安全领域确认的首个在真实攻击中利用AI驱动的勒索软件。它的可怕之处不在于加密强度,而在于它利…

2026/8/7 8:25:46 阅读更多 →

日新闻

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/GitHub_Trending/sc/scrcpy 想要将Android手机屏幕完美投射到电脑上,享受大屏操作的自…

2026/8/7 0:00:19 阅读更多 →
如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南

如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南

如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南 【免费下载链接】tom-select Tom Select is a lightweight (~16kb gzipped) hybrid of a textbox and select box. Forked from selectize.js to provide a framework agnostic autocomplete widget wi…

2026/8/7 0:00:19 阅读更多 →
5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件

5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件

5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件 【免费下载链接】nsz NSZ - Homebrew compatible NSP/XCI compressor/decompressor 项目地址: https://gitcode.com/gh_mirrors/ns/nsz 你是否在为Nintendo Switch游戏文件占用大量存储…

2026/8/7 0:00:19 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/6 22:02:27 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/6 22:02:27 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/6 22:02:27 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/6 22:02:28 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →