从cocos2dx回调看到的std::bind,和lambda表达式

昨天手动binding C++的回调到Lua的时候,用到了lambda表达式。今天专门看了一下cocos2dx的回调操作。都是个人笔记,有问题欢迎指正, 不负任何法律责任,-_-
参考文章, 果冻想

1. 首先也是从这几个回调开始看

#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__)

全是关于std::bind的宏定义。因为cocos2dx中只会用到绑定成员函数的情况,所以,这里只看一下,绑定成员函数的用法。

2.简单看一下std::bind的源码,在functional.h的头文件中。

// TEMPLATE FUNCTION bind (implicit return type)没有返回值
template<class _Fx,
    class... _Types> inline
    _Binder<_Unforced, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args)
    {   // bind a callable object with an implicit return type
    return (_Binder<_Unforced, _Fx, _Types...>(
        _STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...));
    }

    // TEMPLATE FUNCTION bind (explicit return type)有返回值的
template<class _Ret,
    class _Fx,
    class... _Types> inline
    _Binder<_Ret, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args)
    {   // bind a callable object with an explicit return type
    return (_Binder<_Ret, _Fx, _Types...>(
        _STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...));
    }

会发现下面还有一个枚举,是关于参数占位符的枚举,一共20个,所以用std::bind最多支持20个参数的函数的绑定。

3.绑定成员函数

这里主要是看绑定成员函数的基本用法:
首先,我有一个类,需要一个std::function的参数

#include<iostream>
#include <functional>

class MyClass
{
    
public:
    typedef std::function<void(std::string)> myCallBack;

    MyClass(std::string name);
    ~MyClass();
    std::string getName();
    void setName(std::string name);
    void printInfo();
    void setCallBack(myCallBack callBack); //需要一个std::function的方法
private:
    std::string _name;
    myCallBack _callBack;
};

然后看一下调用setCallBack的方法:

auto myClass = MyClass("12121");
myClass.setCallBack(std::bind(&HelloWorld::myClassCallBack/*函数名*/, this/*调用者*/, std::placeholders::_1/*参数*/));

因为myClassCallBack需要一个参数,所以这里草穿进去一个参数占位符,就可以接受调用过程中实际传过来的参数了。如果有多个参数,就需要多个参数占位符。这里的参数占位符也可以替换成这种:

myClass.setCallBack(std::bind(&HelloWorld::myClassCallBack, this, "zzz test!!"));

这样的话,下面的myClassCallBack中传进来的就是"zzz test!!",下面是成员函数:

void HelloWorld::myClassCallBack(std::string str)
{
    CCLOG("===============   %s", str.c_str());
}

4.绑定非成员函数

绑定非成员函数的时候,可以把调用者去掉就可以了:

int add1(int i, int j, int k) {  
    return i + j + k;  
} 
auto add2 = std::bind(add1, std::placeholders::_1, std::placeholders::_2, 10);  
    // 函数add2 = 绑定add1函数,参数1不变,参数2不变,参数3固定为10.  

还有一个需要注意的地方就是参数占位符如果调换位置,在实际调用过程中,传入参数也会调换位置。这样就比较灵活,一个函数通过bind的时候调换参数的位置,设置可以实现函数重载的功能。

5.然后接上面的看一下lambda表达式设置回调

auto func = [](std::string str) {
        CCLOG("==========lambda=======%s", str.c_str());
    };
myClass.setCallBack(func);

这个就比较简单了,具体lambda的用法,以后用到了再深究吧

lambda表达式基本用法

1)声明Lambda表达式

Lambda表达式完整的声明格式如下:

[capture list] (params list) mutable exception-> return type { function body }

各项具体含义如下

  • capture list:捕获外部变量列表
  • params list:形参列表
  • mutable指示符:用来说用是否可以修改捕获的变量
  • exception:异常设定
  • return type:返回类型
  • function body:函数体
2)具体用法
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int> myvec{ 3, 2, 5, 7, 3, 2 };
    sort(myvec.begin(), myvec.end(), [](int a, int b) -> bool { return a < b; });   // Lambda表达式
    cout << "lambda expression:" << endl;
    for (int it : myvec)
        cout << it << ' ';
}
3)捕获外部变量

[]:默认不捕获任何变量;
[=]:默认以值捕获所有变量;
[&]:默认以引用捕获所有变量;
[x]:仅以值捕获x,其它变量不捕获;
[&x]:仅以引用捕获x,其它变量不捕获;
[=, &x]:默认以值捕获所有变量,但是x是例外,通过引用捕获;
[&, x]:默认以引用捕获所有变量,但是x是例外,通过值捕获;
[this]:通过引用捕获当前对象(其实是复制指针);
[*this]:通过传值方式捕获当前对象;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容