cocos2d-x-3.0學習筆記之std::function、std::bind

在C++中,可調用體主要包括函數,函數指針,函數引用,可以隱式轉換爲函數指定的對象,或者實現了opetator()的對象(即C++98中的functor)。C++0x中,新增加了一個std::function對象,std::function對象是對C++中現有的可調用實體的一種類型安全的包裹(我們知道像函數指針這類可調用實體,是類型不安全的)。好了,具體概念不深究,由於自己也是第一次接觸這個,僅僅是將std::function作爲函數指針回調的替代品,具有可靠的安全性和更高的靈活性。
由於自己在工作中遇到的難題是,需要寫一個接口以實現某個功能,而這個功能會被其子類調用,因此很自然的想到在基類中實現這個功能,但是這個功能會調用其子類的成員函數,即這是一個典型的回調問題,此時首先想到的是利用函數指針來做,但這可能涉及到許多的安全轉換問題,再嘗試了一番失敗後就放棄了,然後由於自己是做cocos2d-x開發的,在cocos2d-x的庫代碼裏,就有許多的回調使用了std::function來做回調函數,因此,首先來分析cocos引擎是如何做的,在這裏我分析了 MenuItemImage類的create函數

 MenuItemImage* create(const std::string& normalImage, const std::string& selectedImage, Ref* target, SEL_MenuHandler selector);
 //這個類是用圖片創建一個菜單選項,然後最後一個參數傳進去的就是點擊菜單時的回調處理函數
 //然後我們進入SEL_MenuHandler查看其定義
 typedef void (Ref::*SEL_CallFunc)();
typedef void (Ref::*SEL_CallFuncN)(Node*);
typedef void (Ref::*SEL_CallFuncND)(Node*, void*);
typedef void (Ref::*SEL_CallFuncO)(Ref*);
typedef void (Ref::*SEL_MenuHandler)(Ref*);
typedef void (Ref::*SEL_SCHEDULE)(float);
//通過定義發現cocos定義了許多的函數指針用來處理不同的回調需求,在這裏我們只需要瞭解selector是一個函數指針即可

進入create函數內部繼續跟蹤

MenuItemImage * MenuItemImage::create(const std::string& normalImage, const std::string& selectedImage, Ref* target, SEL_MenuHandler selector)
{
    return MenuItemImage::create(normalImage, selectedImage, "", std::bind(selector, target, std::placeholders::_1));
}
//可以看到其調用了另外一個create函數,記下最後的一個參數:std::bind(selector, target, std::placeholders::_1)

繼續找這個函數的定義

MenuItemImage * MenuItemImage::create(const std::string& normalImage, const std::string& selectedImage, const ccMenuCallback& callback)
{
    return MenuItemImage::create(normalImage, selectedImage, "", callback);
}
//其最後一個參數ccMenuCallbac尋找其定義如下圖所示

這裏寫圖片描述

可以看到其爲 typedef std::function

typedef std::function<void(Ref*)> My_func;
void f(const My_func &pt){...}
//然後調用f時
std::bind(&需要調用的類的成員函數的地址, 調用這個函數的類的對象(this), std::placeholders::_1)
//最後一個參數std::placeholders::_1爲參數佔位符,表示當前還未確定,也可以直接傳遞一個實參進去

總結:std::function和std::bind的使用只要按照其規則還是非常簡單的,但是有幾點需要注意:
1.std::function作爲函數形參時,必須在前加const,否則會報錯
2.被調用的函數爲累的成員函數,必須用std::bind進行綁定

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章