c++的可調用對象 有c++
void afuncToCall() { cout << "call me"<<"\n"; } //1.call function afuncToCall();
void func(int i){ cout << "a function called by function pointer i= "<<i<<"\n"; } //聲明一個函數指針 void(*f)(int i); //對函數指針賦值 f=func; //調用指針函數 f(5);
或者使用typedef縮寫函數指針函數
//function pointer typedef void(*AbleCallFuncP)(int i) ; //2.function pointer AbleCallFuncP callFuncPointer= func; callFuncPointer(5);
auto flambda = [](int i){ cout << "lambda i is " << i << "\n"; }; flambda(7);
#include <functional> void func(int i){ cout << "a function called by bind object i= "<<i<<"\n"; } auto fbind = bind(func,std::placeholders::_1); fbind(9);
struct callableStruct { int operator()(int val){ return (val<0)?-val:val; } }; // callableStruct callableSut; int i = callableSut(-2);
如今,咱們擁有了5種函數調用方式,那麼,在一個項目裏,咱們極可能但願使用一個統一的函數表來管理這些函數調用對象,以上面的函數爲例,咱們其實擁有了5個參數爲int類型的調用對象,使用map能夠方便地實現函數表;指針
只是,問題在於,這5種可調用對象的類型是不一樣的,咱們沒法將他們使用同一種類型放入map的second字段中,因而萬能的C++標準大神們發明了function類模板來解決這個問題。code
羅列5種可調對象以下:對象
//function void afuncToCall(int i) { cout << "call me a plain functon i is "<<i <<"\n"; } //function pointer typedef void(*AbleCallFuncP)(int i) ; //called by function pointer void func1(int i){ cout << "a function called by function pointer i= "<<i<<"\n"; } //called by bind void func2(int i){ cout << "a function called by bind i= "<<i<<"\n"; } //callable class struct callableStruct { void operator()(int i){ cout << "a function called by callableStruct i= "<<i<<"\n"; } };
//1.call function //afuncToCall(); // //2.function pointer AbleCallFuncP callFuncPointer= func1; //3.lambda auto flambda = [](int i){ cout << "lambda i is " << i << "\n"; }; //4 bind auto fbind = bind(func2,std::placeholders::_1); //5.operator () callableStruct callableSut;
讓咱們用function統一它們的類型string
#include <functional> #include <map> #include <string> // using std::map; void TestCallableObj() { typedef function<void(int)> FuncVI; typedef map<string,FuncVI> FuncAbleObjMap; FuncAbleObjMap callableObjMap; callableObjMap.insert(FuncAbleObjMap::value_type(string("plain function call"),afuncToCall)); callableObjMap.insert(FuncAbleObjMap::value_type(string("function pointer call"),callFuncPointer)); callableObjMap.insert(FuncAbleObjMap::value_type(string("lambda call"),flambda)); callableObjMap.insert(FuncAbleObjMap::value_type(string("bind call"),fbind)); callableObjMap.insert(FuncAbleObjMap::value_type(string("operator() call"),callableStruct())); callableObjMap["plain function call"](1); callableObjMap["function pointer call"](2); callableObjMap["lambda call"](3); callableObjMap["bind call"](4); callableObjMap["operator() call"](5); }
輸出結果io
call me a plain functon i is 1 a function called by function pointer i= 2 lambda i is 3 a function called by bind i= 4 a function called by callableStruct i= 5
因而可知,經過function模板,咱們將類型本不一樣的5個可調用對象打包成統一的類型,由於它們的返回值和參數類型是徹底同樣的。經過函數表的使用,咱們能夠寫出封裝更好的調用函數。function
若是以爲這樣的調用太繁瑣,可使用宏來縮寫下
好比:模板
#define CALL1(x) callableObjMap[#x](1); CALL1(plain function call); CALL1(bind call);
備註,本文沒有涉及到函數成員函數 和靜態成員函數的調用,權當歸類到函數一類了。可是其調用細節和函數仍是有差別的。class