仿函数 VS 函数指针实现回调
前提:
本博客对比 函数指针实现回调 和 仿函数 ,突出仿函数的优势。
目的:
一个类要能够灵活的调用两个函数,essfc 和 greaterfc,分别用于比较两个整数的大小:
①:lessfc:判断 x 是否小于 y,如果是则返回 true,否则返回 false。
②:greaterfc:判断 x 是否大于 y,如果是则返回 true,否则返回 false

一:函数指针实现回调
①:普通代码:
//lessfc函数 x<y?
bool lessfc(int x, int y)
{return x < y;
}//greaterfc函数 x>y?
bool greaterfc(int x, int y)
{return x > y;
}// A这个类体现了--->函数指针实现回调
class A
{
public:A(bool(*pf)(int, int))//构造函数接收一个函数指针 并赋值给成员变量:_pf(pf){}void func(int xx, int yy)//func函数接收两个参数{cout << "void func(int xx, int yy)" << _pf(xx, yy) << endl;;} //用接收到的函数指针结合两个int参数调用该函数 bool(*_pf)(int, int);//成员变量也是一个函数指针类型
};int main()
{A aa1(lessfc);//创建一个对象aa1.func(1, 2);//调用对象的func函数 且传两个intA aa2(greaterfc);//创建一个对象aa2.func(1, 2);//调用对象的func函数 且传两个int
}
运行结果:

解释:
类 A 的行为可以通过传入不同的函数指针来动态改变:
传入 lessfc 时,func 方法会执行小于比较。
传入 greaterfc 时,func 方法会执行大于比较。
②:加上模版的代码:
//lessfc函数 x<y?
template<class T>
bool lessfc(T x, T y)
{return x < y;
}//greaterfc函数 x>y?
template<class T>
bool greaterfc(T x, T y)
{return x > y;
}// A这个类体现了--->函数指针实现回调
template<class T>
class A
{
public:A(bool(*pf)(T, T))//构造函数接收一个函数指针 并赋值给成员变量:_pf(pf){}void func(T xx, T yy)//func函数接收两个参数{cout << "void func(T xx, T yy)" << _pf(xx, yy) << endl;;} //用接收到的函数指针结合两个int参数调用该函数 bool(*_pf)(T, T);//成员变量也是一个函数指针类型
};int main()
{A<int> aa1(lessfc);//因为有模版,所以显式传模版的类型去创建一个对象aa1.func(1, 2);//调用对象的func函数 且传两个int 与创建时T的类型吻合A<double>aa2(greaterfc);//因为有模版,所以显式传模版的类型创建一个对象aa2.func(1.1, 1.0);//调用对象的func函数 且传两个double 与创建时T的类型吻合
}

解释:加上模版之后,范围更广了
二:仿函数
定义:一个对象能像函数一样用,实际上调用的是我们重载的 operator()
①:普通代码:
//定义仿函数
class lessfc //将之前的lessfc函数封装成一个类
{
public://类中仅需对()这个操作符进行重载bool operator()(const int& x, const int& y){return x < y;}
};//定义仿函数
class greaterfc //将greaterfc函数封装成一个类
{
public://类中仅需对()这个操作符进行重载bool operator()(const int& x, const int& y){return x > y;}
};template<class Comapre>
class A//A这个类要使用仿函数
{
public:void func(int xx, int yy){Comapre com;//创建一个 Comapre 类型的对象 com。cout << "void func(int xx, int yy)" << com(xx, yy) << endl;;//调用 com(xx, yy),即调用仿函数的 operator(),比较 xx 和 yy。}
};int main()
{A<less<int>> aa1;aa1.func(1, 2); // 输出 1 < 2 的结果(true)A<greater<int>> aa2;aa2.func(1, 2); // 输出 1 > 2 的结果(false)
}
运行结果:

①:不再像函数指针那样,赤裸裸的写两个函数,而是在两个类中对()运算符进行重载,重载的定义在写函数的功能
②:需要用仿函数的类的模版参数,就是那两个仿函数的类名,在类中进行仿函数类的对象的创建,再结合类中函数(如func)的参数,最后结合()进行函数的调用,仿函数对象看见()就会实现重载后的功能
③:main函数中的less<int>,就是对仿函数进行显式的调用,此时的模版不再是简单的类型,而是一个类
②:加上模版的代码:
//定义仿函数
template<class T>
class lessfc //将之前的lessfc函数封装成一个类
{
public://类中仅需对()这个操作符进行重载bool operator()(const T& x, const T& y){return x < y;}
};//定义仿函数
template<class T>
class greaterfc //将greaterfc函数封装成一个类
{
public://类中仅需对()这个操作符进行重载bool operator()(const T& x, const T& y){return x > y;}
};template<class Comapre, class T>
class A//A这个类要使用仿函数
{
public:void func(T xx, T yy){Comapre com;//创建一个 Comapre 类型的对象 com。cout << "void func(T xx, T yy)" << com(xx, yy) << endl;;//调用 com(xx, yy),即调用仿函数的 operator(),比较 xx 和 yy。}
};int main()
{A<less<int>, int> aa1;aa1.func(1, 2); // 输出 1 < 2 的结果(true)A<greater<double>, double> aa2;aa2.func(1.1, 1.0); // 输出 1.1 >1.0 的结果(ture)
}
运算结果:

解释:对三个类都加上模版之后,范围更广了
三:仿函数更优的点
1. 更灵活的功能扩展
仿函数:仿函数是一个类对象,可以包含成员变量和成员函数,因此可以在调用时保存状态(例如计数器、配置参数等)。
函数指针:函数指针只能指向一个静态函数,无法保存状态,功能扩展性较差。
2. 更高的性能
仿函数:仿函数通常是内联的(inline),编译器可以优化其调用,减少函数调用的开销。
函数指针:函数指针的调用需要通过指针间接调用,无法内联,性能稍差。
3. 更强的类型安全
仿函数:仿函数是类对象,类型信息在编译时确定,类型安全性更高。
函数指针:函数指针的类型信息较弱,容易出错(例如指向错误类型的函数)。
4. 更好的通用性
仿函数:仿函数可以与模板结合,实现高度通用的代码。例如,STL 中的排序算法 std::sort 可以通过传入不同的仿函数实现升序或降序排序。
函数指针:函数指针的通用性较差,难以与模板结合。
5. 支持运算符重载
仿函数:仿函数可以重载 operator(),使得对象可以像函数一样被调用,语法更直观。
函数指针:函数指针的调用语法较为繁琐。
6. 更易于组合和扩展
仿函数:仿函数可以通过继承、组合等方式扩展功能。
函数指针:函数指针的功能扩展性较差,难以实现复杂的逻辑组合。

相关文章:
仿函数 VS 函数指针实现回调
前提: 本博客对比 函数指针实现回调 和 仿函数 ,突出仿函数的优势。 目的: 一个类要能够灵活的调用两个函数,essfc 和 greaterfc,分别用于比较两个整数的大小: ①:lessfc:判断 x …...
MQTT的安装和使用
MQTT的安装和使用 在物联网开发中,mqtt几乎已经成为了广大程序猿必须掌握的技术,这里小编和大家一起学习并记录一下~~ 一、安装 方式1、docker安装 官网地址 https://www.emqx.com/zh/downloads-and-install/broker获取 Docker 镜像 docker pull e…...
网络工程师考试详细介绍,讲解,备考方案
一、考试科目与形式 1. 科目1:基础知识(计算机与网络知识) - 考试形式:机考,75道选择题(含5道英文题),满分75分 - 核心内容: - 计算机系统:硬件组成&…...
ROS melodic 安装 python3 cv_bridge
有时候,我们需要处理这些兼容性问题。此处列举我的过程,以供参考 mkdir -p my_ws_py39/src cd my_ws_py39 catkin_make_isolated-DPYTHON_EXECUTABLE/usr/bin/python3 \-DPYTHON_INCLUDE_DIR/usr/include/python3.8 \-DPYTHON_LIBRARY/usr/lib/x86_64-l…...
SHELL练习01
判断一个数是奇数还是偶数 要求: 编写一个 Shell 脚本,用户输入一个整数,判断该数是奇数还是偶数,并输出结果。 [rootnode test01]# touch Determine parity.sh [rootnode test01]# vim Determine parity.sh 还有 2 个文件等待…...
PRODIGY: “不折腾人”的蛋白-蛋白/蛋白-小分子结合能计算工具
PRODIGY(全称为 PROtein binDIng enerGY prediction)是一种蛋白质结合能预测工具,可利用蛋白质-蛋白质复合物的三维结构来预测其结合亲和力。PRODIGY 利用一种高效的基于接触的方法,在估计结合自由能和解离常数的同时,…...
C++之 【模板初阶(函数模板与类模板)】
目录 1.泛型编程 2.模板 3函数模板 3.1函数模板的概念 3.2函数模板的格式 3.3函数模板的原理 3.4函数模板的实例化 3.4.1隐式实例化:让编译器根据实参推演模板参数的实际类型 3.4.2显示实例化:在函数名后的<>中指定模板参数的实际类型 3.…...
博弈论中的均衡精炼:完美贝叶斯均衡、序贯均衡与颤抖手均衡详解
博弈论中的均衡精炼:完美贝叶斯均衡、序贯均衡与颤抖手均衡详解 1. 引言:为什么需要均衡精炼? 在博弈论中,纳什均衡是分析策略互动的核心工具,但其存在一个显著缺陷:无法排除不合理的均衡。例如࿰…...
在线教育网站项目第四步:deepseek骗我, WSL2不能创建两个独立的Ubuntu,但我们能实现实例互访及外部访问
一、说明 上一章折腾了半天,搞出不少问题,今天我们在deepseek的帮助下,完成多个独立ubuntu24.04实例的安装,并完成固定ip,实践证明,deepseek不靠谱,浪费我2个小时时间,我们将在下面实…...
在刀刃上发力:如何精准把握计划关键节点
关键路径分析是项目管理中的一种重要方法,它通过在甘特图中识别出项目中最长、最关键的路径,来确定项目的最短完成时间。 关键路径上的任务都是项目成功的关键因素,任何延误都可能导致整个项目的延期。关键路径分析对于项目管理者来说至关重要…...
组合总和||
1.给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。 #include <bits/stdc.h> using namespace std; vector<vector<int>> result; vec…...
OpenCV图像拼接(2)基于羽化(feathering)技术的图像融合算法拼接类cv::detail::FeatherBlender
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::detail::FeatherBlender 是 OpenCV 中用于图像拼接的一个类,它属于 stitching 模块的一部分。这个类实现了基于羽化(…...
MediaPipe软件包如何构建和安装
MediaPipe 是一个由 Google 开发的多媒体机器学习框架,支持多种平台(如 Android、iOS、桌面等)。以下是构建和安装 MediaPipe 的步骤: 1. 环境准备 确保系统满足以下要求: 操作系统: Ubuntu (推荐 18.04 或 20.04)、…...
分享下web3j 常见用法
转账 fun sendEthTransaction(privateKey: String,toAddress: String,amount: BigDecimal) {//chainIdval chainId:Long 1//url 可以从https://chainlist.org/里面获取可用节点//eth转账,bnb同理,但需发送到bnb对应节点val url "https://xxx"…...
连接chatgpt的桌面语音助手
要创建一个连接到 ChatGPT 的桌面语音助手,可以使用 Python 编写一个程序来实现语音识别、与 ChatGPT API 交互以及语音合成的功能。以下是一个完整的解决方案和技术实现步骤: 所需工具和库 语音识别 使用 speech_recognition 库捕获用户的语音输入。需要…...
systemctl restart 和 systemctl reload 和 systemctl daemon-reload 对比 笔记250322
systemctl restart 和 systemctl reload 和 systemctl daemon-reload 对比 以下是 systemctl restart、systemctl reload 和 systemctl daemon-reload 的对比总结: 命令作用对象行为适用场景对服务的影响systemctl restart 服务名具体服务强制停止服务,…...
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能示例9,TableView15_09带排序的导出表格示例
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
spring boot 登入权限RBAC模式
首先准备好5张表 user_info表,用户的信息表 role表,角色表(比如超级管理员、管理员、审核员、采购......) 创建user_role表,user_info表,role表的中间表 注意了,role_id和user_id是 u…...
调用API拿到的值——存储方式
1.响应结果示例: "purposeTagList":["稳中向好及进中提质"] 2.数据库中定义的 3.值的获取: F1 JsonNode purposeTagListNode dataNode.path("purposeTagList");if (purposeTagListNode.isArray()) {StringBuilder purp…...
【用 Trace读源码】PlanAgent 执行流程
前提条件 在 Trae 中打开 OpenManus 工程,使用 build 模式,模型选择 claude-sonnet-3.7 提示词 分析 agent/planning.py 中 main 方法及相关类的执行流程,以流程图的方式展示PlanningAgent 执行流程图 以下流程图展示了 PlanningAgent 类…...
第一讲 | 解锁C++编程能力:基础语法解析
C入门基础 一、C的第一个程序二、命名空间三、C输入&输出四、缺省参数/默认参数五、函数重载六、引用1.引用的特性2.引用的使用引用做返回值场景 3.const引用只有指针和引用涉及权限放大、缩小的问题,普通变量没有 4.指针和引用的关系 七、inline八、nullptr 一…...
LeetCode 热题 100_划分字母区间(80_763_中等_C++)(贪心算法(求并集))
LeetCode 热题 100_划分字母区间(80_763) 题目描述:输入输出样例:题解:解题思路:思路一(贪心算法(求交集)): 代码实现代码实现(思路一(贪心算法(求…...
C++ --- 多态
1 多态的概念 多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运⾏时多 态(动态多态),这⾥我们重点讲运⾏时多态,编译时多态(静态多态)和运⾏时多态(动态多态)。编译时 多态(静态多态)主要就是我…...
HAL库中使用空闲中断+DMA接收数据,接收失败的问题
问题: 串口屏与单片机通过串口(USART1)进行通信,调试时发现问题,现象如下: 手动页面的几个文本,输入的数字不会显示出来,比如初始值为0,输入200,200会一闪而…...
【STM32实物】基于STM32的扫地机器人/小车控制系统设计
基于STM32的扫地机器人/小车控制系统设计 演示视频: 基于STM32的扫地机器人小车控制系统设计 简介:扫地机器人系统采用分层结构设计,主要包括底层硬件控制层、中间数据处理层和上层用户交互层。底层硬件控制层负责对各个硬件模块进行控制和数据采集,中间数据处理层负责对采…...
【Scrapy】Scrapy教程8——处理子链接
通过前面几篇文章,已经了解了如何去爬取网页内容并存储到数据库,但是目前只是存储了一个页面的内容,现在想要获取每篇文章链接内的文章内容,我们来看看怎么获取。 生成新请求 首先我们肯定要先拿到链接,所以第一步都获取文章标题和链接肯定少不了,然后再爬取获取到到子…...
使用pycel将Excel移植到Python
1.适用需求 有些工作可能长期适用excel来进行公式计算,当需要把工作流程转换为可视化界面时,开发人员不懂专业逻辑,手动摸索公式很大可能出错,而且费时费力 2.可用工具及缺点 pandas 方便进行数据处理,支持各种格…...
学习应用层
应用层概述 客户/服务器方式(C/S)和对等方式(P2P) 动态主机配置协议DHCP 客户/服务器方式 DHCP报文会被封装成为UDP用户数据报,DHCP服务器端口号是UDP67,用户是UDP68。 广播发送,是因为并不知道…...
Doris官网上没有的一些Fe参数了,都在源码中
一、FE配置源码 apache-doris-src\fe\fe-common\src\main\java\org\apache\doris\common\Config.java 二、BE配置源码 apache-doris-src\be\src\common\config.cpp 三、FE源码 package org.apache.doris.common;public class Config extends ConfigBase {ConfField(descri…...
蓝桥杯算法精讲:二分查找实战与变种解析
适合人群:蓝桥杯备考生 | 算法竞赛入门者 | 二分查找进阶学习者 目录 一、二分查找核心要点 1. 算法思想 2. 适用条件 3. 算法模板 二、蓝桥杯真题实战 例题1:分巧克力(蓝桥杯2017省赛) 例题2:砍竹子࿰…...
