新闻详情

新闻详情

首页 / 资讯中心 / 详情

面向对象的三大特性之一——多态

发布时间:2026/9/7 21:45:36来源:尧图网络
面向对象的三大特性之一——多态
概念通俗来说就是多种形态。多态分为编译时多态静态多态)和运行时多态动态多态)我们重点介绍运行时多态。编译时多态静态多态主要就是我们前面讲的函数重载和函数模板他们传不同类型的参数就可以调用不同的函数通过参数不同达到多种形态之所以叫编译时多态是因为他们实参传给形参的参数匹配是在编译时完成的我们一般把编译时归为静态运行时归为动态运行时多态具体点就是去完成某个行为函数情况不同行为就会随之不同传不同的对象就会完成不同的行为就达到多种形态。比如买票这个行为当普通人买票时是全价买票学生买票时是优惠买票军人买票时是优先买票具体来说多态是一个继承关系的下的类对象去调用同一函数产生了不同的行为多态的实现条件1、必须由基类的指针或引用来调用 因为只有基类的指针或引用才能既指向基类对象又指向派生类对象2、被调用的函数是虚函数类成员函数前加关键字virtual即成虚函数非成员函数不能加virtual派生类必须对基类的虚函数完成重写/覆盖派生类中有一个跟基类完全相同的虚函数即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同但参数的默认值可以不同就构成虚函数的重写/覆盖在重写基类虚函数时派生类的虚函数在不加virtual关键字时虽然也可以构成重写因为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性但是该种写法不是很规范不建议这样使用。不过在考试选择题中经常会故意买这个坑让你判断是否构成多态这段代码的输出结果是什么默认参数是在编译时静态绑定的当编译到“func();”此时处在类 A 的作用域编译器看到的是 A 声明的“func(int val 1)”,编译时期直接改写代码为“func(1)”。p是指向类B的一个对象的指针test()函数被继承到派生类Bp-test()指调用test()函数从前面类和对象的知识我们知道成员函数的参数列表隐含有当前类类型基类A的指针thisp传给thisfunc(1);其实是“this-func(1);”构成多态执行结果是B-1。p-func()不构成多态是派生类调用自己的成员函数执行结果是B-0。协变了解派生类重写基类虚函数时可以与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指针或者引用派生类虚函数返回派生类对象的指针或者引用时称为协变。协变的实际意义并不大所以我们了解一下即可析构函数的重写分析此段代码有什么问题只能保证派生类B的基类成员部分释放掉但自己的成员没有释放。那怎么解决呢多态将基类和派生类的析构函数前加virtual可还不满足多态的条件函数名不同为此C的创造者设立了一个规则编译后析构函数的函数名均被改为destructor这也回答了上一部分中为什么基类、派生类的析构函数构成隐藏关键字override和finalC对多态虚函数重写的要求比较严格如果考虑不周没有实现出多态编译时不会报错等到程序结果不符合预期调试才能发现问题C11为了帮助用户检测是否重写新增了override关键字如果不想派生类重写某虚函数可以在虚函数后面加final格式同override。至此我们已经知道了关键字final的两个用法另一个是让类无法继承总结重载/隐藏/重写的对比重载两个函数在同一作用域函数名相同参数列表不同个数不同/类型不同返回值可以相同也可以不同隐藏两个函数分别在继承体系的父类或子类中函数名相同由此不构成重写就会是隐藏父类子类的成员变量名称相同也会构成隐藏类型不同也会隐藏重写两个函数分别在继承体系的父类或子类中函数名、参数列表、返回值相同协变有点例外两个函数都是虚函数纯虚函数与抽象类virtual 返回类型 函数名(参数) 0;在虚函数的后面写上0则这个函数为纯虚函数不需要写函数体也可以有函数体但极少用。包含纯虚函数的类叫做抽象类抽象类不能实例化出对象如果派生类继承后不重写纯虚函数那么派生类也是抽象类。纯虚函数某种程度上强制了派生类重写虚函数因为不重写实例化不出对象多态的原理虚函数表指针从我们前面类和对象的知识来看这段代码的结果是8但这里不同类中有虚函数底层与普通类的对象不同还多了一个_vfptr的指针32位下4字节64位下8字节放在对象内存空间的开头那么_vfptr是什么呢它是虚函数表指针v是virtualf是function它指向一个函数指针数组节省空间不用将所有虚函数指针存放在对象内存中里面存放的是当前对象的所有虚函数指针。虚函数表简称为虚表多态的机理那是系统是如何实现基类的指针/引用来调用所指向对象的虚函数呢C/C调用函数有两种方式1、函数在当前文件声明定义一起编译器在编译时就可以直接确定函数地址2、函数声明与定义分离编译器在链接时确定函数地址。满足多态条件后虚函数调用并不是这两种情况而是运行时到指向对象的虚表中确定所调用虚函数的地址动态绑定与静态绑定对不满足多态条件指针或者引用调用虚函数的函数调用是在编译时绑定也就是编译时确定调用函数的地址叫做静态绑定满足多态条件的函数调用是在运行时绑定也就是在运行时到指向对象的虚函数表中找到调用函数的地址也就做动态绑定虚函数表基类对象的虚函数表中存放基类所有虚函数的地址。同类型的对象共用同一张虚表不同类型的对象各自有独立的虚表所以基类和派生类有各自独立的虚表派生类由两部分构成继承下来的基类和自己的成员一般情况下继承下来的基类中有虚函数表指针自己就不会再生成虚函数表指针。但是要注意的这里继承下来的基类部分虚函数表指针和基类对象的虚函数表指针不是同一个就像基类对象的成员和派生类对象中的基类对象成员也独立的派生类中重写的基类的虚函数派生类的虚函数表中对应的虚函数就会被覆盖成派生类重写的虚函数地址派生类的虚函数表中包含1)基类的虚函数地址2)派生类重写的虚函数地址完成覆盖3派生类自己的虚函数地址三个部分虚函数表本质是一个存虚函数指针的指针数组一般情况这个数组最后面放了一个0x00000000标记。这个C并没有进行规定各个编译器自行定义的VS系列编译器会再后面放个0x00000000标记g系列编译不会放虚函数存在哪的虚函数和普通函数一样的编译好后是一段指令都是存在代码段的只是虚函数的地址又存到了虚表中虚函数表存在哪的这个问题严格说并没有标准答案C标准并没有规定VS下是存在代码段常量区
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

带时滞系统的协方差交叉融合估计:Matlab实现与卡尔曼滤波对比 2026/9/8 0:10:06

带时滞系统的协方差交叉融合估计:Matlab实现与卡尔曼滤波对比

在实际工程中,多传感器融合并不是简单的“多测几次取平均”。尤其是当系统存在时滞——比如通信网络传输延迟、传感器处理时间、执行器响应滞后——融合算法如果没把这段时间差处理好,再精密的滤波也可能发散。我最近在Matlab里完整实现了一个带时滞的线…

阅读更多 →
ITIL4发布计划如何避免假交付?落地的发布管理实战指南 2026/9/8 0:10:06

ITIL4发布计划如何避免假交付?落地的发布管理实战指南

“ITIL4发布计划:90%的运维团队都在‘假交付’?”——这个标题我在行业群里看到第一眼就乐了,数据是否精确到90%我不较真,但“假交付”这三个字确实戳中了我这些年见过的太多运维团队。什么叫假交付?就是你发布计划写了…

阅读更多 →
机器学习与人工智能:从零搭建环境到核心算法实战 2026/9/8 0:10:06

机器学习与人工智能:从零搭建环境到核心算法实战

聊机器学习与人工智能,我见过太多人一上来就背神经网络结构、刷SVM推导,结果越学越懵。根子不在智力,而在没搞清楚这两个词的关系,更没弄明白自己到底该从哪里下手。人工智能是一个很大的目标,机器学习是实现它的核心技…

阅读更多 →
综合能源服务大数据运营体系:从概念到落地的关键路径 2026/9/8 0:10:06

综合能源服务大数据运营体系:从概念到落地的关键路径

综合能源服务这几年在电力行业里被反复提起,但从“概念热”走到“落地稳”,中间隔着一条很深的沟——数据。做了几年电力大数据项目,我最大的感受是:综合能源服务的大数据运营体系,真正难的不是算法,不是平…

阅读更多 →
基于MOPSO的计及光伏波动性主动配电网有功无功协调优化Matlab实现 2026/9/8 0:10:06

基于MOPSO的计及光伏波动性主动配电网有功无功协调优化Matlab实现

基于多目标粒子群优化算法的计及光伏波动性的主动配电网有功无功协调优化(Matlab代码实现)搞配电网优化这块的同行,对“主动配电网”这个词应该都不陌生。传统配电网是被动接收电能,但随着分布式光伏大规模接入,电压越…

阅读更多 →
若依Spring Cloud版本实操指南:从项目启动到微服务排错全记录 2026/9/8 0:07:05

若依Spring Cloud版本实操指南:从项目启动到微服务排错全记录

看到标题进来的,多半是准备用若依Spring Cloud版本搭项目的朋友。我最近刚好把一个内部系统从若依单体版迁到了RuoYi-Cloud微服务版,中间踩了不少坑,也把官方文档里没写透的东西补了一遍。这篇就纯粹是我的实操记录,从版本选型、项…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞