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自动推断的类型,同时又不缺失函数的功能,简直太美妙了。
本文来自博客园,作者:hugeYlh,转载请注明原文链接:https://www.cnblogs.com/helloylh/p/17209705.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通