C++ STL:function包装函数详解


function函数包装将一个复杂的函数包装成一个简单易看易懂的普通函数
语法:

function < 函数返回类型(函数参数…)>

!!!!!在阅读本节前,我建议你应该首先了解这些知识:!!!!!!
什么是仿函数???
bind参数绑定怎么用???

function包装

1.包装普通函数


int add(int a, int b)
{
	return a + b;
}
int main()
{
	//包装普通函数
	function<int(int,int)> F1(add);
	cout << F1(5, 10) << endl;
	return 0;
}

我们创建了一个普通的函数,这个函数接受两个int型数据,返回他们相加的值,我们使用function指定了一个int为返回值,两个int为参数的包装函数,这样我们创建的F1就已经包装好了add函数,可以使用直接列表初始化,也可以使用=赋值初始化,此后,就可以直接调用这个包装函数了。
在这里插入图片描述


2.包装成员函数

class Foo
{
public:
	mutable int a, b;
	Foo() = default;
	Foo(const int& a, const int& b) :a(a), b(b){}
	void Class()
	{
		cout << __FUNCTION__ << endl;
	}
	void operator()(int a, int b)
	{
		cout << __FUNCTION__ << ": " << a * b << endl;
	}
};
int main()
{	
	//包装成员函数:首先要进行bind绑定
	Foo a;
	function<void(int,int)> F2_1 = bind(&Foo::operator(),Foo(), placeholders::_1, placeholders::_2);
	function<void()> F2_2 = bind(&Foo::Class, Foo());
	F2_1(5,122);
	F2_2();
	return 0;
}

我们具有一个类,类中有我们自己定义的成员函数,我们可以把成员函数包装成普通函数。
注意:

  • 类成员函数的包装需要使用bind函数绑定为普通函数,然后进行包装。
  • bind函数的用法:
    bind绑定函数详解

在function中,我们指定bind绑定后的函数为void返回类型,两个int的参数,这样我们的F2_1就是一个普通的接受两个int的参数,返回void的函数了。
在这里插入图片描述


3.包装函数对象(仿函数)

class Foo
{
public:
	mutable int a, b;
	void operator()(int a, int b)
	{
		cout << __FUNCTION__ << ": " << a * b << endl;
	}
};
int main()
{
	//包装函数对象(仿函数)
	function<void(int,int)> F3 = bind(Foo(), placeholders::_1, placeholders::_2);
	F3(50, 40);
	return 0;
}

仿函数:就是一个实现了重载括号运算符的函数,包含了一些实现算法的基本功能:
C++STL仿函数详解
假设你已经知道了仿函数,并且了解了bind 的函数工作原理,同样,我们使用function包装仿函数也需要一个bind先绑定为普通函数,然后再对绑定后的函数起个别名:
定义其为返回类型void,接受两个int类型的参数,这样我们的F3就是这个类型了,即接受两个int,返回void,我们可以很轻松的调用这个函数。
在这里插入图片描述

4.包装lambda表达式

int main()
{
	//包装lambda表达式
	function<void(const int&,const int&)> F4 = bind([](const int& a, const int& b) {cout <<__FUNCTION__<<" :: " << a << ": " << b << endl; }, placeholders::_1, placeholders::_2);
	F4(669, 999);
	return 0;
}

同样使用bind函数进行一次绑定,然后对F4函数进行包装,将此lambda表达式包装成一个接受int类型(const int& 类型也行),然后返回值为void 的普通函数,这样就能调用这个包装的函数了。
在这里插入图片描述


5.对标准库函数再封装

我们知道,在# include < function >文件中定义了很多的仿函数,我们能否直接借用他们,来当作我们自己的函数呢?

int main()
{
	//function偷取标准库函数
	function<bool(int, int)> My_greater = bind(greater<int>(), placeholders::_1, placeholders::_2);
	cout << boolalpha << My_greater(50, 10) << endl;
	function<bool(int)> My_less = bind(less<int>(), placeholders::_1, 20);
	cout << boolalpha << My_less(10) << endl;
	return 0;
}

bind的第一个参数实际上就是个仿函数不过是标准库自带的仿函数,我们应该能很容易的看懂这个代码,他就是标准库自己封装的比较两个数字大于或者其他关系的仿函数,重载了括号运算符,我们完全可以自己写一个仿函数,不过如果你很懒,你可以直接使用function和bind函数绑定并且包装成你自己的函数,然后随意调用。
在这里插入图片描述
在这里插入图片描述


为什么要用function包装?

我们可以思考一下为什么要使用function包装

这是使用auto自动推断出的bind绑定成员函数后的函数类型:

auto F2_1 = bind(&Foo::operator(),Foo(), placeholders::_1, placeholders::_2);

F2_1的类型:std::_Binder<std::_Unforced,void (__cdecl Foo::*)(int,int),Foo,std::_Ph< 1 > const &,std::_Ph< 2 > const &>

对,你没看错,就是这样的,也就是说,如果你要自己手写它的数据类型,让你对着抄你都抄不对,所以我们必须使用auto来自动推断bind函数的类型。

但是我们使用auto未免不直观,我们可以使用function自动包装成简单的类型,只需要指定原函数的返回类型和参数类型即可:

function<void(int,int)> F2_1 = bind(&Foo::operator(),Foo(), placeholders::_1, placeholders::_2);

包装后的F2_1的函数类型:std::function<void __cdecl(int,int)>

是不是一眼就看出来了,这是一个接受两个int,返回类型为void的函数,这样我们简化了auto自动推断的类型,同时又不缺失函数的功能,简直太美妙了。

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yuleo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值