函数与回调:
bind:是函数适配器的增强,可以适配任意可调用对象,包括了函数指针、函数引用、函数对象,把它们变成一个新的函数对象。
function库:对函数指针类型的增强,能容纳任意的可调用对象,配合bind。
signals库:实现了观察者模式。
——————————————————————————————————-----------------------------------------1)bind:函数适配器bind1st/bind2st的泛化和增强,可以适配任意可调用对象,包括函数指针+函数引用+函数对象;
2)最多可绑定9个函数参数;3)bind的真正威力在于他的占位符,占位符可以取代bind中参数的位置,发生函数调用时才接受真正的参数。
bind(func,_2,_1)(a1,a2)
2、使用1)完全可以代替bind1st,bind2nd:
2)完全可以代替mem_fun,mem_fun_ref,来配合标准算法使用
例如:
struct point
{
int x,y;
point(a=0,b=0):x(a),y(b){}
void print()
{cout<<x<<y;
}
};
vector<point>v(10);
for_each(v.begin(),v.end(),bind(&point::print,_1));3)还可以绑定成员变量:
vector<point>v(10);
vector<point>v2(10);
transform(v.begin(),v.end(),v2.begin(),bind(&point::x,_1));
4)代替compose2:
例如:统计vector容器中是否有大于5并且小于10的元素
std::vector<int> ints;
ints.push_back(7);
ints.push_back(4);
ints.push_back(12);
ints.push_back(10);
int count=std::count_if(ints.begin(),
ints.end(),
boost::bind(std::logical_and<bool>(),boost::bind(std::greater<int>(),_1,5),boost::bind(std::less_equal<int>(),_1,10))
);
5)绑定虚函数:class base {
public:
virtual void print() const
{ std::cout << "I am base.\n";
}
virtual ~base() {}
};
class derived : public base
{
public:
void print()const
{ std::cout << "I am derived.\n"; }
};
void main()
{
derived d;
base b;
boost::bind(&base::print,_1)(b);
boost::bind(&base::print,_1)(d);
}
6)实现select1st,select1st的功能,直接选择出pair对象的first,second成员
typedef pair<int,string>pair_t;
pair_t p(123,"zpp"):
cout<<bind(&pair_t::first,p)();
cout<<bind(&pair_t::second,p)();--------------------------------------------------------------------------------------------------------------------------------
可以ptr_fun,mem_fun, 或mem_fun_ref
编写很多小的函数对象的缺点:
1, 大量的小类分散在代码中,这样很难进行维护
2, 理解函数对象被调用处的代码会很难,因为有一部分的功能被定义在别的地方。
2) 使用嵌套的循环结构, 把算法表达式写入循环中。详细用法见:http://blog.csdn.net/huazhongkejidaxuezpp/article/details/20300463
--------------------------------------------------------------------------------------------------------------------------------
像函数对象的容器,以对象的形式封装了原始的函数指针或函数对象,能容纳任意符合函数签名的可调用对象。
即可以容纳任意有operator()的类型(普通函数,成员函数,函数指针,函数对象,lambda表达式,bind)。
作用:用于回调机制,暂时保管函数或函数对象。
被存的函数的最大用途是它可以被多次调用,而无须在创建function时立即使用;
当需要存一个可调用物用于回调时,最好使用function(优于函数指针);
把回调作为类的一个成员时:只能使用function。2、用法
-----------------------------------------------------------------------------------------------------------------------------------------------------------
1)signals2:实现线程安全的观察者模式
观察者模板被称为:信号/插槽,它是一种函数回调机制。一个信号关联了多个插槽,当信号发出时,所有关联它的插槽都会被调用。
2)插槽:可以是可调用对象,包括函数指针+函数对象+它们的bind表达式和function对象。
3) 信号发生时依据组号的排序准则依次调用插槽函数。
各编组调用顺序:组号小---->大 可以改变;
每个编组的插入顺序:at_back,at_front指定;
未被编组的插槽如果位置标志是at_front,在所有编组前被调用;
未被编组的插槽如果位置标志是at_back,在所有编组后被调用;
例子:
template<int N>
struct slots
{
void operator()()
{cout<<N<<endl;}
};
signal<void()>sig;//指定插槽类型,其他模板参数默认值
sig.connect(slots<1>(),at_back);最后被调用
sig.connect(slots<100>(),at_front);第一个被调用
sig.connect(5,slots<11>(),at_back);第四个被调用
sig.connect(5,slots<12>(),at_front);第三个被调用
sig.connect(3,slots<12>(),at_front);第二个被调用
sig();