C++11中的std::bind

最近在看看cocos2dx的源代码,发现了cocos2dx 3.0相对于2.0改动了不少,最大的改变就是大量的使用了C++11的特性,好比auto等。其中有一个关于回调函数绑定的宏定义就使用了std::bind特性ios

// new callbacks based on C++11
#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)

很是简练的宏定义,对于没有接触过C++11的朋友来讲,真的是一头雾水,这货是什么,真的是C++吗?因此笔者就写了这篇文章来说解。编程

C++发展的历史

C++通过多年发展,真正正式公布出的标准只有三个C++98,C++03,C++11。其中C++03只是C++98的小幅度修订,在笔者看来,C++发展的历史,就是一个不断吸取新特性的历史。从最先的面向过程,面向对象,模板编程,到如今的函数式编程,C++一直都是在吸取新特性。lambda就是函数式编程闭包的特性。闭包

何为bind

bind是这样一种机制,它能够预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调 用实体,这种机制在回调函数的使用过程当中也颇为有用。其实最先在C++98的时候,就已经有了std::bind1st和std::bind2nd分别用来绑定functor的两个参数,具体代码就不演示了,查查资料就知道了。这个特性在当时并无引发太多的重视,能够说是食之无味。
C++11中提供了std::bind,能够说是一种飞跃的提高,bind自己是一种延迟计算的思想,它自己能够绑定普通函数、全局函数、静态函数、类静态函数甚至是类成员函数。函数式编程

#include <iostream>
#include <functional>
using namespace std;

int TestFunc(int a, char c, float f)
{
    cout << a << endl;
    cout << c << endl;
    cout << f << endl;

    return a;
}

int main()
{
    auto bindFunc1 = bind(TestFunc, std::placeholders::_1, 'A', 100.1);
    bindFunc1(10);

    cout << "=================================\n";

    auto bindFunc2 = bind(TestFunc, std::placeholders::_2, std::placeholders::_1, 100.1);
    bindFunc2('B', 10);

    cout << "=================================\n";

    auto bindFunc3 = bind(TestFunc, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
    bindFunc3(100.1, 30, 'C');

    return 0;
}

从上面的代码能够看到,bind可以在绑定时候就同时绑定一部分参数,未提供的参数则使用占位符表示,而后在运行时传入实际的参数值。函数

PS:绑定的参数将会以值传递的方式传递给具体函数,占位符将会以引用传递。this

众所周知,静态成员函数其实能够看作是全局函数,而非静态成员函数则须要传递this指针做为第一个参数,因此std::bind能很容易地绑定成员函数。
cocos2dx中的CC_CALLBACK系列的宏其实就是一种封装好的std::bind,它默认认为绑定的就是成员函数,帮助开发者简化了代码。spa

总结

bind最终将会生成一个可调用对象,这个对象能够直接赋值给std::function对象,而std::bind绑定的可调用对象能够是Lambda表达式或者类成员函数等可调用对象,这个是cocos2dx中的通常用法。它能随意绑定任何函数,将全部的函数都能统一到std::function指针

相关文章
相关标签/搜索