最近在看看cocos2dx的源代碼,發現了cocos2dx 3.0相對於2.0改動了不少,最大的改變就是大量的使用了C++11的特性,好比auto
等。其中有一個關於回調函數綁定的宏定義就使用了std::bind
特性ios
// 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++98,C++03,C++11。其中C++03只是C++98的小幅度修訂,在筆者看來,C++發展的歷史,就是一個不斷吸取新特性的歷史。從最先的面向過程,面向對象,模板編程,到如今的函數式編程,C++一直都是在吸取新特性。lambda
就是函數式編程閉包的特性。閉包
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
衆所周知,靜態成員函數其實能夠看作是全局函數,而非靜態成員函數則須要傳遞this指針做爲第一個參數,因此std::bind
能很容易地綁定成員函數。
cocos2dx中的CC_CALLBACK
系列的宏其實就是一種封裝好的std::bind
,它默認認爲綁定的就是成員函數,幫助開發者簡化了代碼。spa
bind
最終將會生成一個可調用對象,這個對象能夠直接賦值給std::function
對象,而std::bind綁定的可調用對象能夠是Lambda表達式或者類成員函數等可調用對象,這個是cocos2dx中的通常用法。它能隨意綁定任何函數,將全部的函數都能統一到std::function
指針