对STL的增加之函数对象篇:实现函数与回调bind/Lambda/function/signals

函数与回调:

bind:是函数适配器的增强,可以适配任意可调用对象,包括了函数指针、函数引用、函数对象,把它们变成一个新的函数对象。

function:对函数指针类型的增强,能容纳任意的可调用对象,配合bind。

signals:实现了观察者模式。

——————————————————————————————————-----------------------------------------

bind

1、特点

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)();

--------------------------------------------------------------------------------------------------------------------------------

 Lambda

1、特点
1)就地定义匿名函数,提高代码的可读性和可维护性; 避免代码膨胀和功能的分散。

可以ptr_fun,mem_fun, mem_fun_ref

编写很多小的函数对象的缺点:

1,  大量的小类分散在代码中,这样很难进行维护

2,  理解函数对象被调用处的代码会很难,因为有一部分的功能被定义在别的地方。

2) 使用嵌套的循环结构, 把算法表达式写入循环中。

详细用法见:http://blog.csdn.net/huazhongkejidaxuezpp/article/details/20300463

--------------------------------------------------------------------------------------------------------------------------------

function

1、特点

像函数对象的容器,以对象的形式封装了原始的函数指针或函数对象,能容纳任意符合函数签名的可调用对象。

                                  即可以容纳任意有operator()的类型(普通函数,成员函数,函数指针,函数对象,lambda表达式,bind)。

作用:用于回调机制,暂时保管函数或函数对象。

被存的函数的最大用途是它可以被多次调用,而无须在创建function时立即使用;

当需要存一个可调用物用于回调时,最好使用function(优于函数指针);

把回调作为类的一个成员时:只能使用function。

 2、用法

  对STL的增加之函数对象篇:实现函数与回调bind/Lambda/function/signals_第1张图片

      对STL的增加之函数对象篇:实现函数与回调bind/Lambda/function/signals_第2张图片

-----------------------------------------------------------------------------------------------------------------------------------------------------------

Signals2 观察者模式

1、特点

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();





你可能感兴趣的:(对STL的增加之函数对象篇:实现函数与回调bind/Lambda/function/signals)