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.mfbz.cn/a/326652.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

测试 ASP.NET Core 中间件

正常情况下&#xff0c;中间件会在主程序入口统一进行实例化&#xff0c;这样如果想单独测试某一个中间件就很不方便&#xff0c;为了能测试单个中间件&#xff0c;可以使用 TestServer 单独测试。 这样便可以&#xff1a; 实例化只包含需要测试的组件的应用管道。发送自定义请…

从源码中分析SDS相较于C字符串的优势

文章目录 前言Type && EncodingsdsencodingcreateStringObjectcreateEmbeddedStringObject总结 createRawStringObject总结 createStringObjectFromLongDouble总结 createStringObjectFromLongLongWithOptions总结 相关操作sdscatlen总结 阈值44sds VS C字符串 前言 从…

数据完整性

数据完整性 一、实验目的 掌握使用SQL语句CREATE TABLE定义约束的方法。掌握使用SQL语句ALTER TABLE增加或删除约束的方法。了解约束的各种类型。掌握使用SQL语句CREATE TRIGGER创建触发器的方法。掌握引发触发器的方法。掌握使用SQL语句DROP TRIGGER删除触发器的方法。 二、…

扫雷游戏【可展开一片,超详细,保姆级别,此一篇足够】

一、C语言代码实现的扫雷游戏的运行 C语言实现扫雷 二、扫雷游戏的分析与设计 1.扫雷游戏的界面设计 在玩家玩扫雷的时候&#xff0c;它会给你一个二维的棋盘&#xff08;下面的讲解都以9x9规格为例子&#xff09;&#xff0c;然后点击你想排查的坐标&#xff0c;若不是雷的&…

KubeSphere 核心实战之一【在kubesphere平台上部署mysql】(实操篇 1/3)

文章目录 1、登录kubesphere平台2、kubesphere部署应用分析2.1、工作负载2.2、服务2.3、应用路由2.4、任务2.5、存储与配置2.6、部署应用三要素 3、部署mysql3.1、mysql容器启动实例3.2、mysql部署分析3.3、创建mysql的配置3.4、创建mysql的数据卷pvc3.5、创建mysql工作负载3.6…

MySQL之导入导出远程备份(详细讲解)

文章目录 一、Navicat导入导出二、mysqldump命令导入导出2.1导出2.2导入&#xff08;使用mysqldump导入 包含t_log表的整个数据库&#xff09; 三、LOAD DATA INFILE命令导入导出3.1设置;3.2导出3.3导入(使用单表数据导入load data infile的方式) 四、远程备份4.1导出4.2导入 一…

市场下行,中国半导体进口数量、金额双双两位数锐减 | 百能云芯

根据中国海关总署最新统计&#xff0c;2023年中国累计进口集成电路&#xff08;半导体晶圆&#xff09;数量为4795亿颗&#xff0c;较2022年下降10.8%&#xff1b;而进口金额为3494亿美元&#xff0c;下降15.4%。这一数据显示&#xff0c;中国半导体进口在数量和金额两方面均出…

第十三课:eNSP BGP协议教程

系列文章目录 第一课&#xff1a;eNSP第一个网络拓扑配置教程 第二课&#xff1a;eNSP vlan网络拓扑图配置教程 第三课&#xff1a;eNSP WIFI网络拓扑配置教程 第四课&#xff1a;eNSP 路由器路由配置拓扑教程 第五课&#xff1a;eNSP DHCP拓扑配置教程 第六课&#xff1…

林江院长:让斜视的孩子改“斜”归正,“正视”未来

读写时跳行、不敢和别人对视、拍照时不敢看镜头......这些不便是不少斜视患儿每天都在经历的日常。 斜视是目前儿童常见的眼科疾病之一&#xff0c;该眼病不仅给孩子的外在形象带来影响&#xff0c;更重要的是会影响双眼视功能及身心健康&#xff0c;其危害不容小觑。 7岁男孩晓…

Microsoft Remote Desktop for Mac 中文正式版下载 微软远程连接软件

Microsoft Remote Desktop 是一款专为 Mac 用户设计的远程桌面工具&#xff0c;它可以帮助用户通过网络连接到其他计算机&#xff0c;实现远程控制和操作。 软件下载&#xff1a;Microsoft Remote Desktop for Mac 中文正式版下载 该工具支持多种远程连接协议&#xff0c;包括 …

Python高级编程之IO模型与协程

更多Python学习内容&#xff1a;ipengtao.com 在Python高级编程中&#xff0c;IO模型和协程是两个重要的概念&#xff0c;它们在处理输入输出以及异步编程方面发挥着关键作用。本文将介绍Python中的不同IO模型以及协程的概念、原理和用法&#xff0c;并提供丰富的示例代码来帮助…

SyntaxError: invalid syntax. Perhaps you forgot a comma?解决办法

Bug分析 1.错误解释2. 示例 1.错误解释 这个错误提示“SyntaxError: invalid syntax. Perhaps you forgot a comma?”表明你的代码中存在语法错误&#xff0c;可能是缺少了一个逗号。 在Python中&#xff0c;逗号用于分隔列表、元组和字典中的元素。如果在创建这些数据结构时…

使用dataframe_image将dataframe表格转为图片

安装方法&#xff1a;pip install dataframe-image 这个库可以将dataframe的表格转换为图片格式&#xff0c;比起数字&#xff0c;图片的格式在手机上会更清晰的看清楚数据及对应行列 示例程序 import numpy as np import pandas as pd import dataframe_imagedef main():my…

OPC UA 开源库编译方法及通过OPC UA连接西门S7-1200 PLC通信并进行数据交换[一]

前言 在现代工业自动化领域&#xff0c;OPC UA&#xff08;开放性生产控制和统一架构&#xff09;是一种广泛应用的通信协议。本文将以通俗易懂的方式解释OPC UA的含义和作用&#xff0c;帮助读者更好地理解这一概念。 一、OPC UA的定义 OPC UA全称为“开放性生产控制和统一…

Spring基础属性一览:注释、对象装配、作用域、生命周期

在Spring中想要更简单的存储和读取对象的核心是使用注解&#xff0c;也就是我们接下来要学的Spring中相关注解。 之前我们存储Bean时&#xff0c;需要在自己添加的配置文件中添加一行bean才行&#xff1a; 而现在我们只需要一个注解就可以替代之前要写的一行配置的繁琐了。 …

基于域账户及西门子simatic logon的集中权限管理的实现(二)

上次我们完成了域环境及simatic logon服务器的搭建&#xff0c;今天我们将在wincc及HMI上进行组态&#xff0c;实现用域账户进行登录。 3.WINCC用户管理组态引文&#xff1a;博途工控人平时在哪里技术交流博途工控人社群 3.1 首先将要安装WINCC的服务器加入域。 3.2 在wincc…

springboot实现黑名单和白名单功能

题外话 关于黑名单和白名单功能&#xff0c;我觉得可以直接用linux服务器的iptables或nftables来实现黑名单和白名单功能。这两个工具都是Linux系统上用于配置防火墙规则的命令行工具。 iptables&#xff1a; 描述&#xff1a; iptables 是一个用于配置IPv4数据包过滤规则的工具…

Netty开篇——NIO章中(四)

通道(Channel) Channel类似于流&#xff0c;有些区别 同时进行读写&#xff0c;而流只能读或者只能写实现异步读写数据可以从缓冲读数据&#xff0c;也可以写数据到缓冲 Channel在 NIO 中是一个接口:public interface Channel extends Closeable{} 常用的Channel类有:FileChan…

【昕宝爸爸小模块】深入浅出之JDK21 中的虚拟线程到底是怎么回事(二)

➡️博客首页 https://blog.csdn.net/Java_Yangxiaoyuan 欢迎优秀的你&#x1f44d;点赞、&#x1f5c2;️收藏、加❤️关注哦。 本文章CSDN首发&#xff0c;欢迎转载&#xff0c;要注明出处哦&#xff01; 先感谢优秀的你能认真的看完本文&…

Arthas项目实战用法

一、简介 1、项目所在位置 2、安装Arthas 1. 下载arthas-boot.jar 2. 运行arthas-boot.jar 3. 选择进程 3、卸载Arthas 二、核心监视功能 1、monitor&#xff1a;监控方法的执行情况 2、watch&#xff1a;检测函数返回值 3、trace&#xff1a;根据路径追踪&#xff0c;…
最新文章