news 2026/7/6 8:30:49

每日一个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/7/6 1:18:11

Open-AutoGLM日志系统揭秘,掌握这6个参数才算真正入门

第一章&#xff1a;Open-AutoGLM日志系统概述Open-AutoGLM 是一个面向自动化生成与智能推理的日志处理框架&#xff0c;专为大规模语言模型任务中的日志采集、结构化分析与异常检测设计。该系统通过统一的日志接口规范和模块化的处理流水线&#xff0c;实现从原始日志输入到语义…

作者头像 李华
网站建设 2026/7/5 5:16:19

jQuery UI 实例 - 放置(Droppable)

jQuery UI Droppable&#xff08;放置&#xff09;实例 jQuery UI 的 Droppable 交互允许将元素定义为“可放置目标”&#xff0c;通常与 Draggable&#xff08;拖动&#xff09;结合使用&#xff0c;实现拖拽放置功能。常用于购物车、垃圾桶、排序列表、回收站等场景。 推荐…

作者头像 李华
网站建设 2026/7/6 8:24:04

探索三相两电平光伏逆变器DC - AC部分的Simulink仿真之旅

三相两电平光伏逆变器dcac部分&#xff0c;simulink仿真&#xff0c;电压电流双闭环控制&#xff0c;空间矢量调制&#xff08;svpwm&#xff09;在光伏逆变器的领域中&#xff0c;三相两电平逆变器是常见且重要的存在&#xff0c;其中DC - AC部分实现了直流到交流的关键转换。…

作者头像 李华
网站建设 2026/7/1 11:33:42

【AI推理服务稳定性提升】:基于Open-AutoGLM的后台运行配置最佳实践

第一章&#xff1a;Open-AutoGLM 后台运行概述Open-AutoGLM 是一个基于 AutoGLM 架构的开源自动化语言模型服务平台&#xff0c;支持在本地或云端长时间后台运行&#xff0c;适用于持续推理、任务调度与API服务部署等场景。为确保服务稳定性与资源利用率&#xff0c;合理配置其…

作者头像 李华
网站建设 2026/7/6 1:19:22

Open-AutoGLM网络配置避坑指南(一线专家亲授12年实战经验)

第一章&#xff1a;Open-AutoGLM网络配置优化概述在部署和运行 Open-AutoGLM 模型服务时&#xff0c;网络配置的合理性直接影响模型推理的响应速度、吞吐能力和整体稳定性。合理的网络优化策略不仅能降低延迟&#xff0c;还能提升多节点协同训练与推理的效率。核心优化目标 最小…

作者头像 李华
网站建设 2026/7/6 2:07:30

Open-AutoGLM报错代码怎么破:从日志到修复的7步闭环流程

第一章&#xff1a;Open-AutoGLM 报错代码查询在使用 Open-AutoGLM 框架进行大模型自动化推理时&#xff0c;开发者常会遇到各类运行时错误。准确识别并解析报错代码是快速定位问题的关键。本章将介绍常见报错类型、其底层成因及对应的排查策略。常见报错类型与含义 ERR_MODEL_…

作者头像 李华