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

相关文章
相关标签/搜索