C++可調用對象與函數表

c++的可調用對象 有c++

  • 函數
  • 函數指針
  • lambda表達式
  • bind的對象
  • 重載了函數調用運算符的類

如何調用?

函數調用

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);

lambda表達式調用

auto flambda = [](int i){
    cout << "lambda i is " << i << "\n";
};
flambda(7);

bind的對象

#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

相關文章
相關標籤/搜索