C++11中的std::bind
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本身是一种延迟计算的思想,它本身可以绑定普通函数、全局函数、静态函数、类静态函数甚至是类成员函数。
#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指针作为第一个参数,所以std::bind能很容易地绑定成员函数。
cocos2dx中的CC_CALLBACK系列的宏其实就是一种封装好的std::bind,它默认认为绑定的就是成员函数,帮助开发者简化了代码。
总结
bind最终将会生成一个可调用对象,这个对象可以直接赋值给std::function对象,而std::bind绑定的可调用对象可以是Lambda表达式或者类成员函数等可调用对象,这个是cocos2dx中的一般用法。它能随意绑定任何函数,将所有的函数都能统一到std::function
example:
#include <iostream>
#include <typeinfo>
#include <functional>
#include <string.h>
#include <iostream>
#include <typeinfo>
#include <functional>
#include <string.h>
using namespace std; int add(int a, int b, int c)
{
return a+b+c;
} class Utils{
public:
Utils(const char* name){
strcpy(_name, name);
} void SayHello(const char* name) const{
std::cout<<_name<<" say : hello "<<name<<endl;
} static int getId(){
return ;
} private:
char _name[];
}; int main()
{
auto add2 = std::bind(add, std::placeholders::_1, , );
int i=add2();
std::cout<<i<<std::endl;
std::cout<<typeid(add2).name()<<endl; cout<<"------------------------------------"<<endl; Utils util("xiaoming");
//绑定类成员
auto sayHello = std::bind(&Utils::SayHello, util, std::placeholders::_1);
sayHello("xiaodonmg"); auto SayHelloKit = std::bind(&Utils::SayHello, util, "kit");
SayHelloKit(); //绑定静态成员
auto getId = std::bind(&Utils::getId);
cout<<getId()<<endl; return ;
}
C++11中的std::bind的更多相关文章
- C++11中的std::function
看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::fun ...
- 【转】C++11中的std::function
原文地址:http://www.jellythink.com/archives/771 看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard: ...
- C++11 中function和bind以及lambda 表达式的用法
关于std::function 的用法: 其实就可以理解成函数指针 1. 保存自由函数 void printA(int a) { cout<<a<<endl; } std:: ...
- c++11中关于std::thread的join的思考
c++中关于std::thread的join的思考 std::thread是c++11新引入的线程标准库,通过其可以方便的编写与平台无关的多线程程序,虽然对比针对平台来定制化多线程库会使性能达到最大, ...
- 关于C++11中的std::move和std::forward
std::move是一个用于提示优化的函数,过去的c++98中,由于无法将作为右值的临时变量从左值当中区别出来,所以程序运行时有大量临时变量白白的创建后又立刻销毁,其中又尤其是返回字符串std::st ...
- [C/C++]关于C++11中的std::move和std::forward
http://www.cnblogs.com/cbscan/archive/2012/01/10/2318482.html http://blog.csdn.net/fcryuuhou/article ...
- c++11中关于`std::thread`线程传参的思考
关于std::thread线程传参的思考 最重要要记住的一点是:参数要拷贝到线程独立内存中,不管是普通类型.还是引用类型. 对于传递参数是引用类型,需要注意: 1.当指向动态变量的指针(char *) ...
- C++11中提供了std::bind
再来看看std::bind C++11中提供了std::bind.bind()函数的意义就像它的函数名一样,是用来绑定函数调用的某些参数的. bind的思想实际上是一种延迟计算的思想,将可调用对象保存 ...
- C++11 中的function和bind、lambda用法
std::function 1. std::bind绑定一个成员函数 #include <iostream> #include <functional> struct Foo ...
随机推荐
- Kotlin扩展作用域分析与扩展的根本作用解析
在上一次https://www.cnblogs.com/webor2006/p/11219358.html学习了Kotlin的扩展,继续这个话题继续拓展,首先提出这么一个问题:假如我们扩展的方法跟类中 ...
- 32位JVM和64位JVM的最大堆内存分别是多数?32位和64位的JVM,int类型变量的长度是多数?
理论上说上 32 位的 JVM 堆内存可以到达 2^32,即 4GB,但实际上会比这个小很多.不同操作系统之间不同,如 Windows 系统大约 1.5 GB,Solaris 大约 3GB.64 位 ...
- 《少年先疯队》第八次团队作业:Alpha冲刺第四天
前言 第四天冲刺会议 时间:2019.6.17 地点:宿舍 4.1 今日完成任务情况以及遇到的问题. 4.1.1今日完成任务情况 姚玉婷:管理员功能模块中,收费管理功能的实现. ...
- 前端知识总结--2 js部分
1. JavaScript的『预解释』与『变量提升』 先看以下代码输出啥? var a= 1; function f() { console.log(a); var a = 2; } f(); 首先答 ...
- 关于Serializable
1.在Java中,只要一个类实现了java.io.Serializable接口,那么它就可以被序列化. 2.通过ObjectOutputStream和ObjectInputStream对对象进行序列化 ...
- BZOJ 2502 清理雪道(有源汇上下界最小流)
题面 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机, ...
- Javaweb学习笔记(一)
一.javaweb学习是所需要的细节 1.发送响应头相关的方法 1).addHeader()与setHeader()都是设置HTTP协议的响应头字段,区别是addHeader()方法可以增加同名的响应 ...
- leetcode解题报告(31):Kth Largest Element in an Array
描述 Find the kth largest element in an unsorted array. Note that it is the kth largest element in the ...
- 洛谷 P1231教辅的组成
题目描述 /* s->练习册(1~b)->书(b+1~a+b)->答案(a+b+1~a+b+c)->t 但是可能会有多本练习册指向同一本书,这本书又可能会指向多本答案 这样每本 ...
- Pytest权威教程02-Pytest 使用及调用方法
目录 Pytest 使用及调用方法 使用python -m pytest调用pytest 可能出现的执行退出code 获取版本路径.命令行选项及环境变量相关帮助 第1(N)次失败后停止测试 指定及选择 ...