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 ...
随机推荐
- P2149 [SDOI2009]Elaxia的路线[最长公共路径]
题目描述 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在 ...
- Vue当中的this
10事件绑定 methods当中的this就是Vue实例对象vm var vm = new Vue({ el: '#app', data: { num: 0 }, // 注意点: 这里不要忘记加逗号 ...
- 三.protobuf3标量值类型
Protobuf3 标量值类型 标量消息字段可以具有以下类型之一——该表显示了.proto文件中指定的类型,以及自动生成的类中的相应类型: .proto类型 说明 C++ 类型 Java 类型 Pyt ...
- 接口-httpClient
最近在工作的过程中有遇到httpClient接口,今天特意些一个小示例对这个知识点进行温习. 下面是代码小片段: package com.sinosoft.lis.mgubq.zhaoyongqian ...
- Leonardo的笔记本LA 3641——置换的乘法
题意 给出26个大写字母的置换 $B$,问是否存在一个置换 $A$,使得 $A^2=B$. 分析 首先,若A=BC,若B和C都能表示成两个相同循环的乘积,则A也能. 因为,不相交的循环的乘积满足交换律 ...
- Kubernetes 学习22 kubernetes容器资源需求资源限制及HeapSter(翻车章节)
一.概述 1.接下来介绍在k8s上运行pod对象时我们如何去监控我们系统级的资源指标以及业务级别的资源指标.数据如何获取和监控.在此之前先介绍一下Pod对象的资源请求和资源限制.即容器的资源需求和资源 ...
- (尚013)Vue的生命周期
三个阶段: 一.初始化显示; 二:更新显示 三.死亡 每一个阶段都对应生命周期的回调函数(也叫勾子函数) 生命周期图示: 1. 2.test013.html <!DOCTYPE html> ...
- CSS滑动门
如下图所示,每个导航栏目的文字个数不一样多,有的长,有的短,如何用一张背景图片,适应不同字数”的导航条,“滑动门”设计的非常巧妙,采用两个相同的背景图像,一左一右,一个负责提供左边框,一个负责提供右边 ...
- Nginx服务配置文件介绍
LNMP架构应用实战——Nginx服务配置文件介绍 nginx的配置文件比较简单,但功能相当强大,可以自由灵活的进行相关配置,因此,还是了解下其配置文件的一此信息 1.Nginx服务目录结构介绍 安装 ...
- CFD计算过程发散诸多原因分析【转载】
转载自: http://blog.sina.com.cn/s/blog_5fdfa7e601010rkx.html 今天探讨引起CFD计算过程中发散的一些原因.cfd计算是将描述物理问题的偏微分方程转 ...