最近在看看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++98,C++03,C++11。其中C++03只是C++98的小幅度修订,在笔者看来,C++发展的历史,就是一个不断吸取新特性的历史。从最先的面向过程,面向对象,模板编程,到如今的函数式编程,C++一直都是在吸取新特性。lambda
就是函数式编程闭包的特性。闭包
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
指针