C++11中的std::bind

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


// 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本身是一种延迟计算的思想,
它本身可以绑定普通函数、全局函数、静态函数、类静态函数甚至是类成员函数。

  1. #include <iostream>
  2. #include <functional>
  3. using namespace std;


  4. int TestFunc(int a, char c, float f)
  5. {
  6.     cout << a << endl;
  7.     cout << c << endl;
  8.     cout << f << endl;


  9.     return a;
  10. }


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


  15.     cout << "=================================\n";


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


  18.     cout << "=================================\n";


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


  21.     return 0;
  22. }



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

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


众所周知,静态成员函数其实可以看做是全局函数,而非静态成员函数则需要传递this指针作为第一个参数,
所以std::bind能很容易地绑定成员函数。


cocos2dx中的CC_CALLBACK系列的宏其实就是一种封装好的std::bind,
它默认认为绑定的就是成员函数,帮助开发者简化了代码。


三、总结
bind最终将会生成一个可调用对象,这个对象可以直接赋值给std::function对象,
而std::bind绑定的可调用对象可以是Lambda表达式或者类成员函数等可调用对象,
这个是cocos2dx中的一般用法。它能随意绑定任何函数,将所有的函数都能统一到std::function
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值