当前位置: 首页 > news >正文

C++之多态(上)

C++之多态

在这里插入图片描述

多态的概念

多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运⾏时多 态(动态多态),这⾥我们重点讲运⾏时多态,编译时多态(静态多态)和运⾏时多态(动态多态)。编译时 多态(静态多态)主要就是我们前⾯讲的函数重载和函数模板,他们传不同类型的参数就可以调⽤不同的 函数,通过参数不同达到多种形态,之所以叫编译时多态,是因为他们实参传给形参的参数匹配是在 编译时完成的,我们把编译时⼀般归为静态,运⾏时归为动态。

运⾏时多态,具体点就是去完成某个⾏为(函数),可以传不同的对象就会完成不同的⾏为,就达到多种 形态。⽐如买票这个⾏为,当普通⼈买票时,是全价买票;学⽣买票时,是优惠买票(5折或75折);军 ⼈买票时是优先买票。再⽐如,同样是动物叫的⼀个⾏为(函数),传猫对象过去,就是”(>ω<) 喵“,传狗对象过去,就是"汪汪"。

多态的定义及实现

多态的构成条件

多态是⼀个继承关系的下的类对象,去调⽤同⼀函数,产⽣了不同的⾏为。⽐如Student继承了 Person。Person对象买票全价,Student对象优惠买票。

实现多态还有两个必须重要条件:
  • 必须指针或者引⽤调⽤虚函数
  • 被调⽤的函数必须是虚函数。

说明:要实现多态效果,第⼀必须是基类的指针或引⽤,因为只有基类的指针或引⽤才能既指向基类也能派⽣ 类对象;第⼆派⽣类必须对基类的虚函数重写/覆盖,重写或者覆盖了,派⽣类才能有不同的函数,多 态的不同形态效果才能达到。

虚函数

类成员函数前⾯加virtual修饰,那么这个成员函数被称为虚函数。注意⾮成员函数不能加virtual修 饰。

class Person 
{public:};virtual void BuyTicket() { cout << "买票全价" << endl;}
虚函数的重写/覆盖

虚函数的重写/覆盖:派⽣类中有⼀个跟基类完全相同的虚函数(即派⽣类虚函数与基类虚函数的返回值 类型、函数名字、参数列表完全相同),称派⽣类的虚函数重写了基类的虚函数。

注意:在重写基类虚函数时,派⽣类的虚函数在不加virtual关键字时,虽然也可以构成重写(因为继承 后基类的虚函数被继承下来了在派⽣类依旧保持虚函数属性),但是该种写法不是很规范,不建议这样 使⽤,不过在考试选择题中,经常会故意买这个坑,让你判断是否构成多态。

 class Person {public:virtual void BuyTicket() { cout << "买票全价" << endl; } };class Student : public Person {public:virtual void BuyTicket() { cout << "买票打折" << endl; }};void Func(Person* ptr){// 这⾥可以看到虽然都是Person指针Ptr在调⽤BuyTicket // 但是跟ptr没关系,⽽是由ptr指向的对象决定的。ptr->BuyTicket();}int main(){Person ps;Student st;Func(&ps);Func(&st);return 0;}
 class Animal{public:virtual void talk() const{}};class Dog : public Animal 
{public:virtual void talk()  const{ 
std::cout << "汪汪" << std::endl;}};class Cat : public Animal
{public:virtual void talk() const{ 
std::cout << "(>^ω^<)喵" << std::endl; 
}};void letsHear(const Animal& animal){animal.talk();}int main(){Cat cat;Dog dog;letsHear(cat);letsHear(dog);return 0;}
多态场景的⼀个选择题

以下程序输出结果是什么()

A: A->0 B:B->1 C:A->1 D:B->0 E:编译出错 F:以上都不正确

class A{public:virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}virtual void test(){ func();}};class B : public A{public:void func(int val = 0){ std::cout<<"B->"<< val <<std::endl; }};int main(int argc ,char* argv[]){B*p = new B;
p->test();return 0;}

这里B是子类,去找子类发现没有子类没有,然后会去继承的父类里面去找,这里也构成多态的关系,这里面有陷阱,满足多态的情况下,调用子类重写的虚函数

在这里插入图片描述

所以答案是B

虚函数重写的⼀些其他问题

协变(了解)

派⽣类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指针或者引 ⽤,派⽣类虚函数返回派⽣类对象的指针或者引⽤时,称为协变。协变的实际意义并不⼤,所以我们 了解⼀下即可。

class A {};class B : public A {};class Person {public:virtual A* BuyTicket() 
{ 
cout << "
买票
全价
" << endl;return nullptr;}};class Student : public Person {public:virtual B* BuyTicket() 
{ 
cout << "
买票
打折
" << endl;return nullptr;}};void Func(Person* ptr){ptr->BuyTicket();}int main(){Person ps;Student st;Func(&ps);Func(&st);return 0;}

析构函数的重写

基类的析构函数为虚函数,此时派⽣类析构函数只要定义,⽆论是否加virtual关键字,都与基类的析 构函数构成重写,虽然基类与派⽣类析构函数名字不同看起来不符合重写的规则,实际上编译器对析 构函数的名称做了特殊处理,编译后析构函数的名称统⼀处理成destructor,所以基类的析构函数加了 vialtual修饰,派⽣类的析构函数就构成重写。

下⾯的代码我们可以看到,如果~A(),不加virtual,那么deletep2时只调⽤的A的析构函数,没有调⽤ B的析构函数,就会导致内存泄漏问题,因为~B()中在释放资源。

注意:这个问题⾯试中经常考察,⼤家⼀定要结合类似下⾯的样例才能讲清楚,为什么基类中的析构 函数建议设计为虚函数。

 class A{public:virtual ~A(){cout << "~A()" << endl;}};class B : public A {public:~B(){ 
cout << "~B()->delete:"<<_p<< endl;delete _p;}protected:int* _p = new int[10];};int main(){A* p1 = new A;A* p2 = new B;// 只有派⽣类Student的析构函数重写了Person的析构函数,下⾯的delete对象调⽤析构函数,才能构成多态,才能保证p1和p2指向的对象正确的调⽤析构函数。delete p1;delete p2;return 0;}
override 和final关键字

从上⾯可以看出,C++对函数重写的要求⽐较严格,但是有些情况下由于疏忽,⽐如函数名写错参数写 错等导致⽆法构成重载,⽽这种错误在编译期间是不会报出的,只有在程序运⾏时没有得到预期结果 才来debug会得不偿失,因此C++11提供了override,可以帮助⽤⼾检测是否重写。如果我们不想让派 ⽣类重写这个虚函数,那么可以⽤final去修饰。

 // error C3668: “Benz::Drive”: 包含重写说明符“override”的⽅法没有重写任何基类⽅法class Car {public:virtual void Dirve(){}};class Benz :public Car {public:virtual void Drive() override { cout << "Benz舒适" << endl; }};int main(){return 0;}
// error C3248: “Car::Drive”: 声明“final”的函数⽆法被“Benz::Drive”重写class Car{public:virtual void Drive() final {}};class Benz :public Car{public:};int main(){return 0;virtual void Drive() { cout << "Benz舒适" << endl; }
重载/重写/隐藏的对⽐

注意:这个概念对⽐经常考,⼤家得理解记忆⼀下

三个概念对比:

重载

1.两个函数在同一作用域

2.函数相同,参数不同,参数的类型或者个数不同,返回值可同,可不同

重写/覆盖

1.两个函数分别在继承体系的父类和子类不同作用域

2.函数名,参数,返回值都必须相同,协变例外

3.两个函数都必须是虚函数

隐藏

1.两个函数分别在继承体系的父类和子类不同作用域

2.函数名相同

3.两个函数只要不构成重写,就是隐藏

4.父子类的成员变量相同也叫隐藏

在这里插入图片描述

纯虚函数和抽象类

在虚函数的后⾯写上=0,则这个函数为纯虚函数,纯虚函数不需要定义实现(实现没啥意义因为要被 派⽣类重写,但是语法上可以实现),只要声明即可。包含纯虚函数的类叫做抽象类,抽象类不能实例 化出对象,如果派⽣类继承后不重写纯虚函数,那么派⽣类也是抽象类。纯虚函数某种程度上强制了 派⽣类重写虚函数,因为不重写实例化不出对象。

 class Car{public:virtual void Drive() = 0;};class Benz :public Car{public:virtual void Drive(){cout << "Benz舒适" << endl;}};
class BMW :public Car{public:virtual void Drive(){cout << "BMW操控" << endl;}};int main(){// 编译报错:error C2259: “Car”: ⽆法实例化抽象类 
Car car;Car* pBenz = new Benz;pBenz->Drive();Car* pBMW = new BMW;pBMW->Drive();return 0;}

相关文章:

C++之多态(上)

C之多态 多态的概念 多态(polymorphism)的概念&#xff1a;通俗来说&#xff0c;就是多种形态。多态分为编译时多态(静态多态)和运⾏时多 态(动态多态)&#xff0c;这⾥我们重点讲运⾏时多态&#xff0c;编译时多态(静态多态)和运⾏时多态(动态多态)。编译时 多态(静态多态)主…...

PySpark单机模式安装教程

目录 1. 环境准备 1.1 安装要求 1.2 检查Python和Java环境 2. 下载并解压Spark 2.1 下载Spark 2.2 解压安装包 3. 配置环境变量 4. 配置Spark 5. 启动Spark Shell 6. 运行测试 7. 关闭Spark Shell 8. 常见问题 8.1 兼容性问题 8.2 环境变量配置 总结 1. 环境准备…...

DEVOPS: 认证与调度

概述 不知道大家有没有意识到一个现实&#xff0c;就是大部分时候&#xff0c;我们已经不像以前一样通过命令行&#xff0c;或者可视窗口来使用一个系统了现在我们上微博、或者网购&#xff0c;操作的其实不是眼前这台设备&#xff0c;而是一个又一个集群 通常&#xff0c;这样…...

ICPC区域赛成都站【赛后回顾+总结】

传送门 前言赛后总结赛后回顾赛后感悟 前言 首先&#xff0c;这是本人本赛季第一场XCPC区域赛&#xff0c;也是本人算竞生涯中第一场XCPC区域赛&#xff08;之前只打过邀请赛和省赛&#xff09;。 赛后总结 然后赛后总结一下&#xff1a;我队天崩开局&#xff0c;我队出师不利…...

保险大模型革新:全面自动化倒计时

摘 要 大模型于保险业不仅是一个技术升级的过程&#xff0c;更是一种商业模式的变革 未来将会是一切都连接着AI的世界——科技杂志《连线》创始主编凯文凯利&#xff08;KevinKelly&#xff09;曾在《5000天后的世界》中预测。 ChatGPT催生大模型热潮已将近两年&#xff0c;…...

《使用Gin框架构建分布式应用》阅读笔记:p212-p233

《用Gin框架构建分布式应用》学习第12天&#xff0c;p212-p233总结&#xff0c;总22页。 一、技术总结 1.JavaScript知识点 (1)class、method (2)function, arrow function, (3)fetch() (4)Promise, then() 2.bootstrap 第5章主要涉及前端技术的运用&#xff0c;作为后…...

点云聚类学习 KMeans/DBSCAN

点云聚类学习--KMeans/DBSCAN OverviewKMeansDBSCAN简单对比 Overview 最近做的东西会处理一些Lidar的点云数据&#xff0c;虽然之前在看Autoware的时候有了解一些聚类的基本原理和实现&#xff0c;但还是稍微再学习一下聚类方法吧&#xff0c;这里就简单记录一下&#xff08;…...

反悔贪心

Problem - C - Codeforces&#xff08;初识反悔贪心&#xff09; 题目&#xff1a; 思路&#xff1a; 代码&#xff1a; #include <bits/stdc.h> #define fi first #define se secondusing namespace std; typedef pair<int,int> PII;string a, b, ans; bool vis…...

汽车软件融合分析

随着汽车智能化、互联化的不断发展&#xff0c;软件在汽车中的重要性日益彰显。从硬件定义汽车&#xff0c;到软件定义汽车&#xff0c;再到AI定义汽车&#xff0c;汽车产业的变革正在加速进行。在这一变革中&#xff0c;软件融合成为了一个重要的趋势。本文将从多个角度对汽车…...

机器人和智能的进化速度远超预期-ROS-AI-

危机 通常&#xff0c;有危险也有机遇才称之为危机。 从2020年启动转型自救&#xff0c;到2021年发现危险迫在眉睫&#xff0c;直到2024年也没有找到自己满意的出路。 共识 中产阶级知识分子共有的特性和一致的推断。 200年前的推断&#xff0c;在如今得到了验证。 机器人…...

5天学习RAG路线图,你信吗?

RAG是"Retrieval Augmented Generation"的缩写&#xff0c;让我们来拆解这个术语&#xff0c;了解RAG的本质&#xff1a; R -> Retrieval&#xff08;检索&#xff09; A -> Augmented&#xff08;增强&#xff09; G -> Generation&#xff08;生成&…...

JIME智创:抖音创作者的AI绘画与视频生成创作神器

在短视频和社交内容创作的时代&#xff0c;创意和速度成了成功的关键。无论是视频博主、图文创作者还是品牌推广人&#xff0c;他们都面临着如何快速生成高质量图片与视频素材的挑战。JIME智创正是针对这一需求推出的AI创作工具&#xff0c;专为抖音的图文和视频创作者设计&…...

基于SpringBoot和PostGIS的世界各国邻国可视化实践

目录 前言 一、空间数据查询基础 1、空间数据库基础 2、空间相邻查询 二、SpringBoot后台功能设计 1、后台查询接口的实现 2、业务接口设计 三、Leaflet进行WebGIS开发 1、整体结构介绍 2、相邻国家展示可视化 四、成果展示 1、印度及其邻国 2、乌克兰及其邻国 3、…...

Halcon相机外参自理解

外参描述了相机在世界坐标系中的位置和朝向&#xff0c;即它将世界坐标转换为相机坐标的几何变换。具体来说&#xff0c;外参包括一个 旋转矩阵 R R R 和一个 平移向量 t t t&#xff0c;它们共同构成了将世界坐标变换到相机坐标系的刚体变换 相机标定的Pose0代表了相机在外界…...

C#语言入门:从基础到进阶

C#&#xff08;发音为"C sharp"&#xff09;是微软公司推出的一种面向对象的编程语言&#xff0c;它由Anders Hejlsberg和他的团队在.NET框架下开发。C#语言结合了C和Java的特性&#xff0c;并添加了新的功能&#xff0c;使其成为当今最流行的编程语言之一。 C#的特…...

网络爬虫的定义

网络爬虫&#xff0c;即Web Spider&#xff0c;是一个很形象的名字。 把互联网比喻成一个蜘蛛网&#xff0c;那么Spider就是在网上爬来爬去的蜘蛛。 网络蜘蛛是通过网页的链接地址来寻找网页的。 从网站某一个页面&#xff08;通常是首页&#xff09;开始&#xff0c;读取网页…...

一个月调研分析标的“英伟达”

放在现在依然成立 一、移动网兴起至今的最佳股票与人工智能时代的目标 9 年移动网兴起至今&#xff0c;若选一只股票长期持有&#xff0c;最佳解是 ARM&#xff08;涨了 20 倍&#xff09;&#xff0c;因为无论系统层和应用层谁胜出&#xff0c;底层一定是芯片&#xff0c;而…...

Spring Boot 与 EasyExcel 携手:复杂 Excel 表格高效导入导出实战

数据的并行导出与压缩下载&#xff1a;EasyExcel&#xff1a;实现大规模数据的并行导出与压缩下载 构建高效排队导出&#xff1a;解决多人同时导出Excel导致的服务器崩溃 SpringBoot集成EasyExcel 3.x&#xff1a; 前言 在企业级应用开发中&#xff0c;常常需要处理复杂的 …...

什么是严肃游戏,严肃游戏本地化的特点是什么?

“严肃游戏”是一种交互式数字体验&#xff0c;不仅用于娱乐&#xff0c;还用于教育、培训或解决问题。与主要关注乐趣和参与度的传统游戏不同&#xff0c;严肃游戏的目标不仅仅是娱乐&#xff0c;比如教授特定技能、模拟现实生活场景或提高对重要问题的认识。它们用于医疗保健…...

ceph补充介绍

SDS-ceph ceph介绍 crushmap 1、crush算法通过计算数据存储位置来确定如何存储和检索&#xff0c;授权客户端直接连接osd 2、对象通过算法被切分成数据片&#xff0c;分布在不同的osd上 3、提供很多种的bucket&#xff0c;最小的节点是osd # 结构 osd (or device) host #主…...

Python AOT编译成本控制实战:2026年前必须掌握的7项硬核降本技术(含CPython 3.15+原生支持验证数据)

第一章&#xff1a;Python AOT编译成本控制的战略定位与2026技术拐点Python长期以来以解释执行和动态特性见长&#xff0c;但其运行时开销与启动延迟在云原生边缘计算、实时AI推理及嵌入式服务场景中日益成为瓶颈。AOT&#xff08;Ahead-of-Time&#xff09;编译正从实验性探索…...

东华OJ-基础题-33-数字之和(C++)

问题描述 输入一个正整数&#xff0c;求这个正整数的各位数字之和。输入说明 你的程序需要从标准输入设备&#xff08;通常为键盘&#xff09;中读入多组测试数据。每组测试数据为正整数&#xff0c;每行一个N&#xff0c;N小于20000输出说明 对每组测试数据&#xff0c;你的程…...

OpenClaw故障排查:百川2-13B-4bits模型接口连接问题解决

OpenClaw故障排查&#xff1a;百川2-13B-4bits模型接口连接问题解决 1. 问题背景与现象描述 上周在尝试将本地部署的百川2-13B-4bits量化模型接入OpenClaw时&#xff0c;遇到了典型的Connection refused错误。这个问题困扰了我整整两天时间&#xff0c;期间尝试了各种常见解决…...

STM32电位器驱动库:轻量级ADC封装与中值滤波实现

1. 项目概述MentorBit-Potenciometro 是一款专为 MentorBit 系统设计的轻量级电位器&#xff08;Potentiometer&#xff09;模块驱动库&#xff0c;面向 STM32 平台&#xff08;典型为 STM32F4/F7/H7 系列&#xff09;的嵌入式固件开发。该库并非通用 ADC 抽象层&#xff0c;而…...

Cuvil + HuggingFace Pipeline端到端加速实录:BERT-base推理延迟从142ms降至31ms的6个关键编译开关

第一章&#xff1a;Cuvil 编译器在 Python AI 推理中的应用 面试题汇总Cuvil 是一款面向 AI 推理场景的轻量级领域专用编译器&#xff08;DSL Compiler&#xff09;&#xff0c;专为优化 Python 中基于 PyTorch/TensorFlow 模型的部署而设计。它通过静态图分析、算子融合与硬件…...

机器人双目视觉定位系统设计与开发

机器人双目视觉定位系统设计与开发 摘要 双目视觉定位技术是机器人感知环境、实现自主导航和精准操作的核心技术之一。本系统基于双目立体视觉原理,利用Matlab平台完成了从相机标定、图像采集、立体匹配到三维坐标解算的完整流程。系统采用张正友标定法获取相机内外参数,通…...

计算机毕业设计springboot长春的地铁综合服务管理系统 基于SpringBoot的城市轨道交通智慧运维管理平台 SpringBoot框架下的地铁运营调度与设备管控系统

计算机毕业设计springboot长春的地铁综合服务管理系统 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。随着城市化进程的加速推进&#xff0c;长春市作为东北地区的重要交通枢纽&…...

WebPlotDigitizer完全指南:从图表图像提取数据的终极解决方案

WebPlotDigitizer完全指南&#xff1a;从图表图像提取数据的终极解决方案 【免费下载链接】WebPlotDigitizer Computer vision assisted tool to extract numerical data from plot images. 项目地址: https://gitcode.com/gh_mirrors/we/WebPlotDigitizer 你是否曾经面…...

保姆级教程:在ROS Noetic下用DWA算法让无人机在已知地图里自动巡航(附完整配置文件)

无人机自主导航实战&#xff1a;ROS Noetic中DWA算法的深度配置与避坑指南 当你在Gazebo仿真环境中看着无人机缓缓升起&#xff0c;准备开始它的首次自主飞行时&#xff0c;那种期待与忐忑交织的感觉&#xff0c;想必每个ROS开发者都深有体会。本文将从实战角度出发&#xff0c…...

G-Helper:重塑华硕硬件控制体验的轻量级开源解决方案

G-Helper&#xff1a;重塑华硕硬件控制体验的轻量级开源解决方案 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, Sca…...