跳至主要內容

函数对象与函数指针

张威大约 4 分钟c/c++STL

函数对象与函数指针

一、函数对象与函数指针

函数对象: 拥有operator()重载函数的对象即函数对象,函数对象,但在C++里为函数对象。

问题一:什么是函数对象呢?

例如:我们C语言进行函数调用与C++中两个函数调用。

在这里插入图片描述
在这里插入图片描述

看起来它们好像一模一样(),但是这里我们就把()运算符重载函数的对象,称作,或者称作

问题二:那么使用函数对象有什么好处呢?

template<typename T>
bool compare(T a, T b)
{
	return a > b;
}

int main()
{
	cout << compare(10, 20) << endl;
	cout << compare('b','y') << endl;

	return 0;
}

我里我们实现了 但是它不够灵活,我们有时想比较小于,每次改动符号有些麻烦,C语言中的函数指针刚好可以很好解决这个问题。

使用C语言中函数指针解决:

//使用C的函数指针解决
template<typename T>
bool mygreater(T a, T b)
{
	return a > b;
}

template<typename T>
bool myless(T a, T b)
{
	return a < b;
}

//compare是C++的库函数模板
template<typename T, typename Compare>
bool compare(T a, T b, Compare comp)
{
	return comp(a, b);
}

int main()
{
	cout << compare(10, 20,mygreater<int>) << endl;
	cout << compare(10, 20,myless<int>) << endl;

	return 0;
}
在这里插入图片描述
在这里插入图片描述

这时,就可以很好的解决这个问题了,我们传入不同的函数指针来解决,想比较大就传入mygreater,想比较小就传入myless,通过函数指针间接调用函数; 但是这里,我们通过函数指针虽然解决了问题,但。因此,C++有一个专门的函数对象来解决这个问题。

使用C++中函数对象解决:

好处:

  1. 通过函数对象调用()运算符重载,可以,比通过函数指针调用函数(不能内联调用)效率高。

  2. 因为函数对象是用类生成的,所以可以添加相关的成员变量用来记录函数对象使用时更多的信息。

//C++函数对象实现
template<typename T>
class mygreater
{
public:
	bool operator()(T a, T b)//二元函数对象
	{
		return a > b;
	}
};

template<typename T>
class myless
{
public:
	bool operator()(T a, T b)//二元函数对象
	{
		return a < b;
	}
};

//compare是C++的库函数模板
template<typename T, typename Compare>
bool compare(T a, T b, Compare comp)
{
	return comp(a, b);//编译过程知道调用对象的函数operator()(a, b);
}

int main()
{
	cout << compare(10, 20,mygreater<int>()) << endl;
	cout << compare(10, 20,myless<int>()) << endl;

	return 0;
}

执行成功:函数对象相比于函数指针

在这里插入图片描述
在这里插入图片描述

二、使用实例

实例1:优先级队列

我们的优先级队列,底层依赖vector容器,底层默认为一个大根堆

int main()
{
	priority_queue<int> que;//底层vector
	for (int i=0; i<10; ++i)//大根堆
	{
		que.push(rand() % 100);
	}

	while (!que.empty())
	{
		cout << que.top() << " ";
		que.pop();
	}
	cout << endl;

	return 0;
}

打印一下:堆顶元素最大

如果我们如何做呢? 只是库中的实现:

template<class _Ty,
	class _Container = vector<_Ty>,
	class _Pr = less<typename _Container::value_type> >

我们将less改为greater即可变为小根堆即可。

using MinHeap = priority_queue<int, vector<int>, greater<int>>;

实例2:set

set底层为红黑树,默认底层从小到大进行输出。底层为:

template<class _Kty,
	class _Pr = less<_Kty>,
	class _Alloc = allocator<_Kty> >
set<int, greater<int>> set;
for (int i=0; i<10; ++i)
{
	set.insert(rand() % 100);
}

for (int v : set)
{
	cout << v << " ";
}
cout << endl;

此时:就是从大到小排序。