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

这篇具有很好参考价值的文章主要介绍了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;
}

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

C++六大组件之一:仿函数,重生之C++启程,c++,开发语言 文章来源地址https://www.toymoban.com/news/detail-803721.html

到了这里,关于C++六大组件之一:仿函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++ ------类和对象详解六大默认成员函数

    如果我们定义一个类,然后这个类中什么也没有。那么这里的类就什么也没有吗?其实不然,任何类在里面什么都不写时,编译器都会生成6个默认成员函数。 用户没有显式实现,编译器会生成的成员函数称为默认成员函数。 六个默认成员函数 我们来看一个Date类 观察上述代

    2024年02月15日
    浏览(50)
  • 【C++】类和对象(中篇)----->六大默认成员函数

    目录 一、类的6个默认成员函数 二、构造函数  1、概念   2、特性 三、析构函数  1、概念  2、特性 四、拷贝构造函数  1、概念  2、特征 五、赋值运算符重载  1、运算符重载  2、值运算符重载    2.1 赋值运算符重载格式    2.2 赋值运算符只能重载成类的成员函数不能

    2024年02月12日
    浏览(40)
  • 【C++干货基地】六大默认成员函数: This指针 | 构造函数 | 析构函数

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 : 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活!   哈喽各位铁汁们好啊,我是博主鸽芷咕《C++干货基地》是由我的襄阳家乡零食基地有感而发,不知道各位的城市有没有这种实惠又全面的零食基地呢?C++ 本身作

    2024年03月11日
    浏览(44)
  • C++入门之stl六大组件--List源码深度剖析及模拟实现

    文章目录 前言 一、List源码阅读 二、List常用接口模拟实现 1.定义一个list节点 2.实现一个迭代器 2.2const迭代器 3.定义一个链表,以及实现链表的常用接口 三、List和Vector 总结 本文中出现的模拟实现经过本地vs测试无误,文件已上传gitee,地址:list: 模仿实现stl的list - Gitee.com 首

    2024年02月13日
    浏览(49)
  • C++入门之stl六大组件--stack和queue源码深度剖析及模拟实现

    目录 前言 一、stack的介绍和使用 1.stack的介绍 2.stack的使用 3.stack的模拟实现 二、queue的介绍和使用 1.queue的介绍 2.queue的使用 3.queue的模拟实现 三、priority_queue的介绍和使用 1.priority_queue的介绍 2.priority_queue的使用 3.priority_queue的模拟实现 3.1解决一个topK问题 四、容器适配器 1

    2024年02月14日
    浏览(47)
  • 【C++】类和对象(中)一篇文章带你学会六大默认成员函数

    如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。 对于下面的date类: 对于Date类,可以通过

    2024年03月12日
    浏览(47)
  • 重生c++系列之类与对象(中篇)

    好的继上期,我们今天带来c++类与对象系列的继续学习。 如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员 函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为

    2024年02月11日
    浏览(36)
  • 重生之我要学C++第五天

    这篇文章主要内容是 构造函数的初始化列表 以及 运算符重载在顺序表中的简单应用 ,运算符重载 实现自定义类型的流插入流提取 。希望对大家有所帮助,点赞+收藏+评论,支持一下吧! 目录 构造函数进阶理解  1.内置类型成员在参数列表中的定义 2.自定义类型成员在参数

    2024年02月15日
    浏览(59)
  • 重生之我要学C++第一天

    我重生了,今天开始带着上世纪的回忆重新学习C++ 目录 命名空间(namespace) 输入输出流 缺省参数(默认参数) 函数重载 新定义命名空间是C++为防止对变量,函数,类 命名冲突 而提出的新的解决措施。是在 全局作用域之外 的自己定义的属于命名空间自己的 特定 域范围

    2024年02月14日
    浏览(33)
  • 重生之我要学C++第四天

    这篇文章的主要内容是 类的默认成员函数 。如果对大家有用的话,希望大家三连支持,博主会继续努力! 目录 一.类的默认成员函数 二.构造函数 三.析构函数 四.拷贝构造函数 五.运算符重载 如果一个类中什么成员都没有,简称为空类。空类中真的什么都没有吗?并不是,

    2024年02月15日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包