相关博文:C++新特性探究(十四):function
相关博文:C++头文件<functional>和bind、placeholders占位符使用简单例子
相关博文:《Essential C++》笔记之设计一个泛型算法(二)
相关博文:C++Function Object Adapter之not1
相关博文:C++之再探参数绑定bind、bind1st、bind2nd、placeholders占位符
相关博文:C++新特性探究(十五):bind
bind语义
bind 用来将可调用对象和参数一起进行绑定。可调用对象包括普通函数、全局函数、静态函数、类静态函数甚至是类成员函数,参数包括普通参数和类成员。绑定后的结果,可以使用 std::function 进行保存,并延迟调用到我们需要的时候。
一. 绑定普通函数与参数及占位
bind绑定的顺序,也就是函数中形参的声明顺序。
placeholders::_x中的序列是实参的顺序。
例1:
运行结果:
附例1代码:
//小问学编程
#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders;
double myDivide(double x,double y)
{
return x/y;
}
int main()
{
//零个参数 return 10/2
auto fn_five=bind(myDivide,10,2);
cout<<fn_five()<<endl;
//一个参数 return x/2 auto不可省
auto fn_half=bind(myDivide,placeholders::_1,2);
cout<<fn_half(10)<<endl;
//一个参数 return 2/x
auto fn_half2=bind(myDivide,2,placeholders::_1);
cout<<fn_half(10)<<endl;
//两个参数 return int x/y
auto fn_rounding=bind<int>(myDivide,_1,_2);
cout<<fn_rounding(10,3)<<endl;
//反转参数 return y/x
auto fn_invert=bind(myDivide,_2,_1);
cout<<fn_invert(10,2)<<endl;
return 0;
}
二. 绑定对象与成员及占位
绑定对象及成员函数时,顺序是调用成员,对象,[参数]。成员,对象及参数不能有缺位,缺位可用 placeholders::_x 来占位。否则编译不过。
例2:
运行结果:
三. 函数重载情形
例3:
//小问学编程
#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders;
int add(int x,int y)
{
cout<<"int add(int x,int y)"<<endl;
return x+y;
}
double add(double x,double y)
{
cout<<"double add(double x,double y)"<<endl;
return x+y;
}
class MyPair
{
public:
int add(int x,int y)
{
cout<<"MyPair::int add(int x,int y)"<<endl;
return x+y;
}
double add(double x,double y)
{
cout<<"double add(double x,double y)"<<endl;
return x+y;
}
};
int main()
{
auto bindGlobalFunc=bind((int(*)(int,int))add,_1,_2);
cout<<bindGlobalFunc(1,2)<<endl;
auto bindGlobalFunc2=bind(static_cast<double(*)(double,double)>(add),_1,_2);
cout<<bindGlobalFunc2(1,2)<<endl;
MyPair mp;
auto bindMemberFunc=bind(static_cast<double(MyPair::*)(double,double)>(&MyPair::add),mp,1,2);
cout<<bindMemberFunc()<<endl;
return 0;
}
运行结果:
四. bind小结
(1)bind 预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的。
(2)对于不事先绑定的参数,需要传 std::placeholders 进去,从_1 开始,依次递增。placeholder 是 pass-by-reference 的。
(3)bind 的返回值是可调用实体,可以直接赋给 std::function 对象。
(4)对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前, 这些参数是可用的。
(5)类的 this 可以通过对象或者指针来绑定。
五. 多态之bind+function
function 本是不可以包装类成员函数,但是 bind 的可以实现类成员函数的绑定, 然后赋给 fucntion 对象,亦即实现了间接性的包装。
bind+function 可以实现接口统一的极大整合,这是多态吗?
例4:
附例4代码:
//小问学编程
#include <iostream>
#include <functional>
using namespace std;
void foo()
{
cout<<"void foo()"<<endl;
}
void func(int a)
{
cout<<"void func(int a)"<<endl;
}
class Foo
{
public:
void method()
{
cout<<"Foo::void method()"<<endl;
}
void method2(string s)
{
cout<<"Foo:void method2()"<<endl;
}
};
class Bar
{
public:
void method3(int a,string s)
{
cout<<"Bar:void method3()"<<endl;
}
};
function<void(void)> f;
int main()
{
f = bind(foo);
f();
f= bind(func,1);
f();
Foo foo;
f = bind(&Foo::method,&foo);
f();
f = bind(&Foo::method2,&foo,"china");
f();
Bar bar;
f = bind(&Bar::method3,&bar,10,"china");
f();
return 0;
}