C++六大组件之一:仿函数

场景一:

与其过多叙述定义,不如在下面一个场景中来理解仿函数:

#include<iostream>
using namespace std;
template<class T>
void bubbles_sort(T* arr,int size) //冒泡排序
{for (int i = 0; i < size - 1; i++){for (int j = 0; j < size - i-1; j++){if (arr[j] > arr[j + 1]){swap(arr[j], arr[j + 1]);}}}
}
int main()
{int arr[6] = { 1,3,2,5,7,4 };bubbles_sort(arr,6);for (auto a : arr){cout << a << " ";}return 0;
}

上面的代码是模板+冒泡函数对指定数组的排序,冒泡函数里面的交换条件是 > ,这样会使排序的结果为升序,如果我们要将冒泡函数的功能改为降序排序,那么只需要将 > 改为 < ,但是有没有办法能更好的封装这个冒泡函数,使得升序降序功能由调用函数时由使用者自己选择?

在C语言中,我们可以用函数指针来实现这个需求,定义两个不同的比较函数,在冒泡函数内部使用函数来比较两值的大小,在调用冒泡函数时实参可以传入不同的比较函数在内部进行比较。

#include<iostream>
using namespace std;template<class T>
void bubbles_sort(T* arr,int size,bool (*com)(T,T))//函数指针
{for (int i = 0; i < size - 1; i++){for (int j = 0; j < size - i-1; j++){if (com(arr[j],arr[j+1]))//调用传入的函数{swap(arr[j], arr[j + 1]);}}}
}template<class T>
bool compare_more(T a, T b)
{return a > b;
}
template<class T>
bool compare_less(T a, T b)
{return a < b;
}int main()
{int arr[6] = { 1,3,2,5,7,4 };bubbles_sort(arr,6, compare_more);//当想要降序排序时,传入compare_less函数即可for (auto a : arr){cout << a << " ";}return 0;
}

C++中如何实现这种需求呢?这里就需要用到仿函数,仿函数本质是利用类的运算符重载,传入函数不同的对象来实现不同的比较。看成果:

#include<iostream>
using namespace std;template<class T>
struct Less
{bool operator()(T a, T b)//重载()运算符{return a < b;}
};
template<class T>
struct More
{bool operator()(T a, T b)//重载()运算符{return a > b;}
};
template<class T,class Compare>
void bubbles_sort(T* arr,int size, Compare com)
{for (int i = 0; i < size - 1; i++){for (int j = 0; j < size - i-1; j++){if (com(arr[j],arr[j+1]))//本质是com.operator(){a,b}{swap(arr[j], arr[j + 1]);}}}
}
int main()
{int arr[6] = {1,3,2,5,7,4};bubbles_sort(arr,6,More<int>());//当想要降序排序,传入Less()对象for (auto a : arr){cout << a << " ";}return 0;
}

场景二:

再来设想一个场景,当一个容器中存放的是学生类的对象时,如何进行排序?

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct Student
{Student(string name,int age,string tele){this->name = name;this->age = age;this->tele = tele;}string name;//姓名int age;//年龄string tele;//电话
};int main()
{vector<Student> v;v.push_back(Student("张三", 18, "12345"));v.push_back(Student("李四", 19, "12321"));v.push_back(Student("张三", 15, "11234"));sort(v.begin(),v.end());//这里会报错,因为学生类没有重载<,导致默认的less<Student>报错for (auto stu : v){cout << "姓名:" << stu.name << "年龄:" << stu.age << "电话:" << stu.tele<<endl;}return 0;
}

上面的代码,直接调用算法库中的sort(),并没有指定学生对象排序是按照什么排序,默认sort函数会用less<Student>里面直接用< 运算符比较两个学生对象,但是学生类并没有重载 < 运算符,就会编译错误。


在这里,我们就可以自己创建一个比较的类,类里面重载()运算符来实现Student的比较方式,在把这个类的对象传入排序函数内部实现比较功能。或者在Student类中重载<运算符。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct Student
{Student(string name,int age,string tele){this->name = name;this->age = age;this->tele = tele;}string name;//姓名int age;//年龄string tele;//电话
};
template<class T>
class Less
{
public:bool operator()(T a, T b)//按年龄比较{return a.age < b.age;}
};
int main()
{vector<Student> v;v.push_back(Student("张三", 18, "12345"));v.push_back(Student("李四", 19, "12321"));v.push_back(Student("张三", 15, "11234"));sort(v.begin(),v.end(),Less<Student>());//传入对象,就可以按照自己定义的方式排序了for (auto stu : v){cout << "姓名:" << stu.name << "年龄:" << stu.age << "电话:" << stu.tele<<endl;}return 0;
}

最后程序的结果是:(按照年龄排序)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/345939.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬虫案例—表情党图片data-src抓取

爬虫案例—表情党图片data-src抓取 表情党网址&#xff1a;https://qq.yh31.com 抓取心情板块的图片data-src 由于此页面采用的是懒加载技术&#xff0c;为了节省网络带宽和减轻服务器压力。不浏览的图片&#xff0c;页面不加载&#xff0c;统一显示LOADING…。如下图&#x…

模拟退火算法(SA)解决旅行商(TSP)问题的python实现

旅行商问题 旅行商问题&#xff08;Travelling Salesman Problem, 简记TSP&#xff0c;亦称货郎担问题)&#xff1a;设有n个城市和距离矩阵D [dij]&#xff0c;其中dij表示城市i到城市j的距离&#xff0c;i, j 1, 2 … n&#xff0c;则问题是要找出遍访每个城市恰好一次的一…

最最常用的MySQL Shell运维脚本,赶紧收藏吧!

作为运维人员或者开发人员&#xff0c;日常的mysql运维工作我们是一定要会的&#xff0c;我收集了一些常用shell脚本&#xff0c;仅供参考&#xff01; 1、备份数据库&#xff1a; #!/bin/bashBACKUP_DIR"backup_dir" MYSQL_USER"mysql_user" MYSQL_PASS…

【Databend】行列转化:数据透视和逆透视

文章目录 数据准备数据透视数据逆透视总结 数据准备 学生学科得分等级测试数据如下&#xff1a; drop table if exists fact_suject_data; create table if not exists fact_suject_data (student_id int null comment 编号,subject_level varchar null comment …

Unity中URP下实现深度贴花(雾效支持和BRP适配)

文章目录 前言一、让我们的贴画支持雾效1、我们舍弃内部的MixFog方法2、使用 雾效混合因子 对最后输出颜色进行线性插值相乘 二、在Shader中&#xff0c;限制贴花纹理的采样方式1、申明 纹理 和 限制采样方式的采样器2、在片元着色器进行纹理采样 三、BRP适配1、C#脚本中&#…

Github Copilot AI保密级教程

Copilot 是一款由 OpenAI 推出的人工智能代码自动补全AI工具&#xff0c;它可以帮助程序员更快、更准确地编写代码。Copilot 的核心技术基于 GPT-3 模型&#xff0c;但是在编码方面是优于GPT-3的&#xff0c;它可以根据程序员输入的上下文和代码提示&#xff0c;自动生成符合语…

2024年美赛数学建模思路 - 复盘:校园消费行为分析

文章目录 0 赛题思路1 赛题背景2 分析目标3 数据说明4 数据预处理5 数据分析5.1 食堂就餐行为分析5.2 学生消费行为分析 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 赛题背景 校园一卡通是集…

AD20 解决PCB铺铜与锡盘之间锯齿状连接问题的设置方法

上一篇文章&#xff1a;PCB简单绘制一般步骤 对上一篇文章中&#xff0c;关于铺铜设置的补充&#xff0c;解决铺铜与锡盘之间的锯齿状连接情况。 1、新建Demo&#xff0c;创建PCB板子&#xff0c;布置锡盘和铺铜&#xff0c;如图&#xff1a; 2、设置规则&#xff0c;参考上一…

Java医院智能3D导诊系统源码 微信小程序源码

医院智慧3D导诊系统&#xff0c; 通过输入疾病症状和选择部位进行导诊挂号&#xff0c;支持小程序端、APP端 开发背景 人们经常去医院因为不知道挂什么科而烦恼&#xff0c;有些病人不方便问又不好意思问。在互联网医院中挂号且又不知该挂什么科&#xff0c;找什么类型的医生&…

聊天机器人之接收实时信息实现(二)

准备工作 如果没有准备好环境的请看 前期环境准备 这里默认已经注入成功并且已经登录好了账号。 具体实现 实现原理 通过本地搭建一个web服务&#xff0c;来接收一个POST请求&#xff0c;这个请求中就会涵盖实时的数据&#xff0c;包括昵称、消息内容、消息类型之类的。 p…

C#销售管理系统源码

C#销售管理系统源码 框架版本: .net framework 4.8 UI控件库:CsKin 功能介绍: 1.登陆 2. 进销存管理&#xff1a;收银台、商品入库、商品浏览、退货 3. 数据统计分析: 销售统计、工资核算 4. 基础数据维护:商品分类管理、员工管理

腾讯云免费服务器怎么申请?腾讯云免费服务器申请难吗?

腾讯云免费服务器申请入口 https://curl.qcloud.com/FJhqoVDP 免费服务器可选轻量应用服务器和云服务器CVM&#xff0c;轻量配置可选2核2G3M、2核8G7M和4核8G12M&#xff0c;CVM云服务器可选2核2G3M和2核4G3M配置&#xff0c;腾讯云服务器网txyfwq.com分享2024年最新腾讯云免费…