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

更好的理解c++中的虚函数和静态多态以及动态多态

1.虚函数(Virtual Function)

在c++ 中, 虚函数是定义在基类中的函数,但是它可以在派生类中进行重写(Override) 。
通过在基类中通过virtual 关键字声明函数 , 你创建了一个可以在任何派生类中特别实现的接口。 当你有一个指针指向基类或者引用, 并通过这个指针或者引用调用虚函数时, c++ 运行时会根据指针或者引用 实际指向的对象来调用适当的函数。 这个过程是在运行时动态发生的, 这也就是所谓的动态绑定或晚绑定 。

2.多态(Polymorphism)

多态是一个通用的概念 , 指的是可以通过同一个接口访问不同类型对象的能力
在c++ 中 多态通常通过虚函数来实现, 当你使用基类的指针或者引用调用一个虚函数时, 实际上会执行派生类版本的函数, 这取决于指针或者引用实际指向的对象类型, 多态允许你编写通用的代码, 这些代码可以与任何从基类派生的类的对象一起工作, 而无需在编译时知道确切的派生类型 。

3. 例子

上面的不太好理解 : 举个简单的例子, 有一天你到餐厅吃饭,服务员给你一张菜单(基类)进行点菜,菜单上有各种食物(派生类) , 但你只需要看菜单就可以做出选择,而不需要知道每种食物是如何准备的
在c++ 中多态就相当于这个菜单 , 它允许你使用一个**通用的接口(基类的指针或引用)**来执行可能有多种不同实现的操作,这意味着我们在写代码的时候不必对象的确切类型, 只需要知道它能干什么 。
其中,虚函数就相当于菜单上的各种食物, 我们可以在基类中声明(virtual), 并且在派生类中重新定义(override)

3.1 代码实现

#include <iostream>
class Food {
public: virtual void prepare(){std::cout << "prepare some food " << std::endl;}
};
class noodele :public Food {
public:void prepare () override {std::cout << "this is your noodel  " << std::endl;}
};
class water :public Food {
public:void prepare() override {std::cout << "this is your water  " << std::endl;}
};void eat(Food* food)
{	//接口要是 : 基类的指针或者引用food->prepare(); //实现多态
}
int main()
{Food* myfood = new water();eat(myfood); delete myfood; 
}

4.注意

虚函数虽然非常好用, 但是在使用虚函数的时候,并不是所有函数都得定义成虚函数,因为实现虚函数是有代价的,需要注意以下几方面的:

  1. **虚析构函数:**如果你的类有虚函数,也应该提供一个虚析构函数,为了确保通过基类指针删除派生类的对象的时候,能够调用正确的析构函数
  2. 内存和性能考虑 : 使用虚函数会增加每个对象的内存开销,以此每个对象需要一个额外的指针来访问虚函数表(v-table) ,此外,虚函数的调用比非虚函数慢,因为需要额外的间接寻址
  3. 虚函数的继承: 一旦在基类中定义了虚函数,它在派生类中自动成为虚函数, 即便没有 virtual 关键字

5. 静态多态和动态多态

  1. 静态多态中, 所有的类型检查和函数调用解析都是在编译时完成的,一次静态多态不会引入运行时的开销
  2. 动态多态 :动态动态主要是运行时进行的 主要通过虚函数实现的 ,在动态多态中, 函数的调用不是在编译时解析的,而是在运行时,当你通过基类的指针或者引用在调用一个虚函数时, c++ 运行时会根据对象的实际类型来确定调用那个函数 。

5.1 函数重载和模板

  1. 函数重载就是指你写了多个重名的函数,但是传入的参数类型或者个数不一样,编译器会根据你传入的参数类型或者参数个数来决定调用那个函数 。
  2. 模板就是一种能够让你的函数或者类能够处理不同数据类型的方法, 你写一次代码,编译器会根据你使用的具体类型来生成多个代码版本
    就比如说使用模板实现不同类型的数据交换
#include <iostream>template <typename T>
void swap(T& a, T& b) {T temp = a;a = b;b = temp;
}int main() {int i = 1, j = 2;swap(i, j);  // 交换两个intstd::cout << "i: " << i << ", j: " << j << std::endl;double x = 3.14, y = 1.59;swap(x, y);  // 交换两个doublestd::cout << "x: " << x << ", y: " << y << std::endl;return 0;
}

5.2总结也就是:

静态多态的类型早已知晓 , 多态性在编译时通过函数重载和模板实现,没有运行开销
动态多态它的类型可能未知, 多态性在运行时通过虚函数实现,这涉及到类型识别,有一定的性能开销

6. 什么函数不能声明为虚函数

  • 普通函数 : 普通函数只能被overload, 不能被override,声明为虚函数也没有意义,因此编译器会在编译时绑定函数
  • 构造函数: 构造函数是为了明确初始化对象成员才产生的, 然而virtual function 主要是为了再不完全了解细节的情况下也能处理对象, 另外virtual function 函数是在不同类型的对象产生不同的对象, 现在对象还没产生,如何使用virtual 函数来完成你想完成的动作 。
  • 静态成员函数: 静态成员函数是不依赖于类的实例,而虚函数是要通过对象的虚表(vtable)来调用
  • 主函数:主函数是程序的入口点,以此不会被声明为虚函数 。

相关文章:

更好的理解c++中的虚函数和静态多态以及动态多态

1.虚函数&#xff08;Virtual Function&#xff09; 在c 中&#xff0c; 虚函数是定义在基类中的函数&#xff0c;但是它可以在派生类中进行重写&#xff08;Override) 。 通过在基类中通过virtual 关键字声明函数 &#xff0c; 你创建了一个可以在任何派生类中特别实现的接口…...

MybatisPlus之新增操作并返回主键ID

在应用mybatisplus持久层框架的项目中&#xff0c;经常遇到执行新增操作后需要获取主键ID的场景&#xff0c;下面将分析及测试过程记录分享出来。 1、MybatisPlus新增方法 持久层新增方法源码如下&#xff1a; public interface BaseMapper<T> extends Mapper<T> …...

工程(十四)——ubuntu20.04 PL-VINS

博主创建了一个科研互助群Q&#xff1a;772356582&#xff0c;欢迎大家加入讨论。这是一个科研互助群&#xff0c;主要围绕机器人&#xff0c;无人驾驶&#xff0c;无人机方面的感知定位&#xff0c;决策规划&#xff0c;以及论文发表经验&#xff0c;以方便大家很好很快的科研…...

C复习-结构struct+bit field+union

参考&#xff1a; 里科《C和指针》 结构的声明 struct {int a;char b; } x; struct {int a;char b; } y[20], *z;// 会报错&#xff0c;因为z和x虽然都没有名字&#xff0c;但是并不是一个东西 z &x;struct SIMPLE {int a;char b; }; // 这样就对了&#xff0c;因为名字匹…...

1 快速了解Paimon数据湖核心原理及架构

1.1 什么是Apache Paimon Apache Paimon的前身属于Flink的子项目&#xff1a;Flink Table Store。 目前业内主流的数据湖存储项目都是面向批处理场景设计的&#xff0c;在数据更新处理时效上无法满足流式数据湖的需求&#xff0c;因此Flink社区在2022年的时候内部孵化了 …...

chrome v3开发插件实现所有网站允许跨域

场景&#xff1a; chrome 插件 升级到v3后&#xff0c;原来修改请求响应都变成异步&#xff0c;即无法同步拦截来修改请求响应。 在v3中也不支持修改请求响应内容。 问题&#xff1a;如何在chrome v3中允许其他网站跨域呢。 方式一&#xff1a;禁用chrome跨域&#xff0c;禁…...

unity Holoens2开发,使用Vuforia识别实体或图片 触发交互

建议&#xff1a;先看官方文档 我使用的utniy 版本&#xff1a;Unity 2021.3.6f1 官方建议&#xff1a;混合现实工具包简介 - 设置项目并使用手势交互 - Training | Microsoft Learn 配置了正确工具的 Windows 10 或 11 电脑Windows 10 SDK 10.0.18362.0 或更高版本安装了 U…...

从零开始搭建微服务(一)

构建项目父工程 添加公共核心模块 安装nacos 安装nacos nacos 文档地址&#xff1a; https://nacos.io/zh-cn/docs/what-is-nacos.html 本文使用版本2.2.2 下载地址&#xff1a;https://github.com/alibaba/nacos/archive/refs/tags/2.2.2.zip 使用nacos 我们下载是源代码 解…...

一种可以实现安全便捷文件摆渡的跨网文件安全交换软件

为了保护数据的安全性和完整性&#xff0c;很多企业都采用了内外网物理隔离的方式&#xff0c;防止核心数据泄露或被恶意篡改。然而&#xff0c;这也给企业内部或与外部合作伙伴之间的文件交换带来了很多不便和挑战。如何在保证数据安全的前提下&#xff0c;实现跨网文件的快速…...

『 MySQL数据库 』数据库基础之表的基本操作

文章目录 创建表&#x1f5e1;查看表&#x1f5e1;✒ 查看表内所有信息(描述\表结构等)✒ 根据条件查看表内数据✒ 查看表的具体详细信息: 修改表&#x1f5e1;✒ 修改表名:✒ 修改表的存储引擎、编码集(字符集和校验集):✒ 表内插入数据:insert into✒ 在表中新添一个字段(列)…...

如何提高40%的Docker构建时间

1. 背景 在产品开发中构建docker镜像,随着时间的推移,会变得越来越大,构建时间也越来越长。我的目标是构建时间不超过 5 分钟。 2. 遵循Dockerfile的最佳实践 我们首先确保Dockerfile文件遵循Docker官方的最佳实践,具体做法有: 尽量使用官方的基础镜像,Docker推荐使用…...

真正解决jellyfin硬解码转码

前段时间入手一个DS423集成显卡UHD600&#xff0c;搭了一个jellyfin&#xff0c;发现网上关于硬解码的教程基本都存在问题&#xff0c;没有真正解决我的硬解码问题。经过一系列分析修改&#xff0c;最终实现硬解码。先贴效果图&#xff1a; 下载安装jellyfin这里就不叙述&#…...

声音训练数据集哪里找?中文、英文

一般找数据集的都是需要训练底膜的&#xff0c;大家git上找的开源项目大多是预训练模型。预训练就是别人已经训练好的底膜&#xff0c;你在他的基础上进行调整。而我们训练如果他这个模型不理想是需要训练底膜的。 找的方式是从git开源上找 中文 推荐MockingBird&#xff0c;…...

springboot中如何同时操作同一功能

问题描述 测试阶段&#xff0c;由于存在某一功能的同时操作&#xff0c;该功能还是入库逻辑&#xff0c;此时若不进行处理&#xff0c;会造成插入表中多条重复数据&#xff0c;为此该问题需要修复。 解决办法 在接口开始进行对是否存在某个key值的判断&#xff0c;若不存在&…...

YOLOWeeds: 用于棉花生产系统中多类杂草检测的 YOLO 目标检测器的新基准

YOLOWeeds: A novel benchmark of YOLO object detectors for multi-class weed detection in cotton production systems 摘要1、介绍2、总结 摘要 过度依赖除草剂控制杂草&#xff0c;加速了杂草的抗除草剂进化&#xff0c;引起了对环境、食品安全和人类健康的日益关注。自动…...

Vue3:自定义图标选择器(包含 SVG 图标封装)

文章目录 一、准备工作&#xff08;在 Vue3 中使用 SVG&#xff09;二、封装 SVG三、封装图标选择器四、Demo 效果预览&#xff1a; 一、准备工作&#xff08;在 Vue3 中使用 SVG&#xff09; 本文参考&#xff1a;https://blog.csdn.net/houtengyang/article/details/1290431…...

NIO讲解

一&#xff1a;什么是NIO? 二&#xff1a;NIO三大组件 1. channel channel 有一点类似于 stream&#xff0c;它就是读写数据的双向通道&#xff0c;可以从 channel 将数据读入 buffer&#xff0c;也可以将 buffer 的数据写入 channel&#xff0c;而之前的 stream 要么是输入…...

react中jest配置,解决node_modules报错esm无法解析的问题

重点关注&#xff1a; transformIgnorePatterns: [ "/node_modules/(?!(?:jmfe)/)", ], moduleNameMapper: { "\\.(css|less|scss|sss|styl)$": "jest-css-modules" } 并安装jest-css-modules&#xff08;npm i --save-dev jest-css-mo…...

Qt6,使用 UI 界面完成命令执行自动化的设计

一、需要完成的功能 在子对话框&#xff08;CmdChildQt&#xff09;中&#xff0c;点击 “执行” 按钮&#xff0c;将多个命令行指令&#xff0c;依次输入到父对话框&#xff08;CmdQt&#xff09;的编辑框中并且执行&#xff0c;要求如下&#xff1a; 在前一个命令执行完成后&…...

Apache Maven;会话技术

Apache Maven是一个项目管理和构建工具&#xff0c;它基于项目对象模型&#xff08;POM&#xff09;的概念&#xff0c;通过一小段描述信息来管理项目的构建、报告和文档。 Maven模型有&#xff1a; 项目对象模型、依赖管理模型、插件 会话技术&#xff1a; 会话&#xff1a…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...