news 2026/6/15 15:36:13

每日一个C++知识点|面向对象之多态

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
每日一个C++知识点|面向对象之多态

C++面向对象的三大特性是封装,继承,多态。上两篇文章分别讨论了封装和继承,今天主要是讲解C++的另一个面向对象的特性~~多态

多态的概念

什么是多态呢?
多态的核心是"同一个接口,不同的实现"
简单来说,就是调用同一个函数名,程序会根据上下文和调用对象的实际类型来自动执行对应的函数逻辑,后面我们将会用代码来举例说明

多态的分类

C++多态分为静态多态动态多态

静态多态

静态多态是编译时多态,编译器在编译阶段就确定要调用的函数版本,主要通过函数重载、模板实现,用代码举例如下:

#include<iostream>usingnamespacestd;// 重载1:计算两个整数的和intadd(inta,intb){returna+b;}// 重载2:计算三个浮点数的和doubleadd(doublea,doubleb,doublec){returna+b+c;}intmain(){cout<<add(12)<<endl;// 调用int版本,输出3cout<<add(1.12.23.3)<<endl;// 调用double版本,输出6.6return0;}

这里编译器根据参数的个数、类型,在编译时就确定了要调用的add()函数

动态多态

动态多态是运行时多态,程序在运行阶段才确定要调用的函数版本

动态多态的实现需要以下三个条件

  1. 存在继承关系
  2. 父类声明虚函数,子类重写该虚函数
  3. 使用父类的指针指向子类对象

由于还没有说到虚函数,暂时先不用代码举例,等说完虚函数再一并举例

虚函数

上面说到虚函数是动态多态实现的必要条件之一,那么什么是虚函数呢?

普通虚函数

虚函数是在父类中用virtual关键字修饰的成员函数,调用时要根据对象的实际类型来动态绑定,而不是编译时固定绑定

// 父类:图形classShape{public:// 虚函数:绘制图形virtualvoiddraw(){cout<<"绘制基础图形"<<endl;}doublegetArea(){return1;}};

上述代码中,用virtual关键字修饰的draw()函数就是虚函数,调用时要根据对象的实际类型来决定其内容,假如它的子类如下所示:

// 子类:圆形classCircle:publicShape{private:doubleradius;public:Circle(doubler):radius(r){}// 重写父类的虚函数(override关键字可选,但建议加)voiddraw()override{cout<<"绘制半径为"<<radius<<"的圆形"<<endl;}doublegetArea(){returnM_PI*radius*radius;}};

上述代码中子类Circle的成员函数draw()有关键字override来修饰,是对父类虚函数draw()的重写,假如调用情况如下所示:

intmain(){// 父类指针指向子类对象(多态的关键)Shape*shape=newCircle(5.0);// 调用的是子类Circle的draw和getArea(动态绑定)shape->draw();// 输出:绘制半径为5的圆形cout<<"面积:"<<shape->getArea()<<endl;// 输出:面积:78.5398deleteshape;return0;}

由于实际的对象由Shape* shape = new Circle(5.0);决定,所以draw()函数是执行Circle类的内容而不是父类Shape的内容

这就是虚函数的内容,也是动态多态的内容(满足动态多态的三个条件)

虚函数的实现原理

我们已经知道了虚函数的用法,那么虚函数是怎么实现动态多态的呢?下面我们简单了解其原理

编译器为了实现虚函数的动态绑定做了两件事:分别是创建虚函数表添加虚表指针

虚函数表是每个包含虚函数的类(包括父类和子类)都会有一个独立的虚函数表,表中存储了该类所有虚函数的地址。上述代码中Shape类和Circle类都有各自的虚函数表,表中存储虚函数draw()的地址

虚表指针是每个对象会包含一个隐藏的虚表指针,指向所属类的虚函数表。上述代码Shape* shape = new Circle(5.0);中的对象shape存在一个虚函数指针,指向Circle类里的虚函数表里的draw()的地址

当程序运行时,通过对象的虚表指针找到对应的虚函数表,再调用表中的函数地址,从而实现 “根据对象实际类型调用函数”

纯虚函数

上述虚函数的例子是有实际意义的,有时候父类的虚函数没有实现意义,这时可以定义纯虚函数,格式是在函数后加 = 0

classShape{public:// 纯虚函数:没有函数体,强制子类必须重写virtualdoublegetArea()=0;// 普通虚函数可以有默认实现virtualvoiddraw(){std::cout<<"绘制基础图形"<<std::endl;}virtual~Shape(){}};

包含纯虚函数的类称为抽象类,不能实例化对象,只能作为基类被继承,同时子类必须重写所有纯虚函数

虚析构函数

当类中有虚函数时,必须将析构函数声明为虚函数,否则会导致内存泄漏,代码如下:

#include<iostream>#include<cmath>usingnamespacestd;classShape{public:// 1. 业务虚函数(多态的核心接口)virtualvoiddraw()=0;// 纯虚函数,强制子类实现virtualdoublegetArea()=0;// 2. 虚析构函数(配合多态删除场景,必须加)virtual~Shape(){cout<<"Shape析构"<<endl;}};classCircle:publicShape{private:doubleradius;public:Circle(doubler):radius(r){}// 重写业务虚函数voiddraw()override{cout<<"绘制圆形,半径:"<<radius<<endl;}doublegetArea()override{returnM_PI*radius*radius;}~Circle()override{cout<<"Circle析构"<<endl;}};intmain(){// 多态场景:父类指针指向子类对象Shape*shape=newCircle(5.0);shape->draw();// 调用子类的draw(业务虚函数的作用)deleteshape;// 调用子类的析构(虚析构函数的作用)return0;}

上述代码中由于Shape类和Circle类都有虚函数,所以必须要有虚析构函数,避免内存泄漏

如果想更深入了解虚析构函数可以看我往期关于虚析构函数的文章,那里有更具体的描述~

总结

本文通过动态的概念、分类、虚函数、纯虚函数、虚析构函数这几个方面来描述了C++面向对象之多态的内容,并通过具体代码示例来深入分析多态的实现原理和演示多态的实现过程

本文暂时写到这里,如果文章对你有用的话欢迎点赞收藏~

感兴趣的话也可以关注我,我会持续输出C++相关的内容~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 12:15:09

【Open-AutoGLM进程管理终极指南】:掌握高效自动化运维的5大核心技巧

第一章&#xff1a;Open-AutoGLM进程管理工具概述Open-AutoGLM 是一款专为自动化大语言模型任务调度与进程控制设计的轻量级管理工具。它支持多任务并行执行、资源监控、异常恢复以及命令模板化配置&#xff0c;适用于本地开发与生产环境部署。该工具基于 Go 语言开发&#xff…

作者头像 李华
网站建设 2026/6/15 6:25:52

基于Java旅游民宿信息管理系统

摘 要 二十一世纪我们的社会进入了信息时代&#xff0c;信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针对这一…

作者头像 李华
网站建设 2026/6/15 11:45:51

Linux系统下Open-AutoGLM开机自启失败?常见问题与解决方案,一篇搞定

第一章&#xff1a;Open-AutoGLM开机自启失败&#xff1f;问题定位与核心思路在部署 Open-AutoGLM 服务时&#xff0c;配置系统级开机自启是保障服务高可用的关键步骤。然而&#xff0c;部分用户反馈服务未能随系统启动自动运行&#xff0c;表现为进程未启动或依赖资源缺失。此…

作者头像 李华
网站建设 2026/6/15 11:47:30

中小学教学新助手:用Linly-Talker制作趣味知识短视频

中小学教学新助手&#xff1a;用Linly-Talker制作趣味知识短视频 在一间普通的教室里&#xff0c;一名数学老师正准备讲解“圆的周长”。以往她需要花半小时录制视频、剪辑字幕、配音润色——而现在&#xff0c;她只需上传一张自拍照&#xff0c;输入一段文字&#xff0c;三分钟…

作者头像 李华
网站建设 2026/6/15 11:47:41

揭秘Open-AutoGLM循环任务设置:3步实现无人值守AI推理流水线

第一章&#xff1a;Open-AutoGLM循环任务设置的核心概念Open-AutoGLM 是一种基于大语言模型的自动化任务执行框架&#xff0c;其核心在于构建可循环、自反馈的任务处理流程。通过定义清晰的任务边界与输出格式&#xff0c;系统能够在无需人工干预的情况下持续优化执行策略&…

作者头像 李华
网站建设 2026/6/15 15:00:00

探索机器视觉:从工业相机采集到模板匹配

机器视觉&#xff0c;OpenCV&#xff0c;Qt&#xff0c;工业相机采集&#xff0c;图像采集&#xff0c;图像处理&#xff0c;卡尺工具&#xff0c;找线&#xff0c;找圆&#xff0c;颜色检测&#xff0c;模板匹配&#xff0c;形状匹配&#xff0c;海康工业相机采集基于形状的模…

作者头像 李华