• C++通过一个函数名的字符串调用对应的函数


    函数按名调用

    假设现有多个函数,如果要根据输入的名字和参数进行相应的调用,如果是在python,可以直接将一个函数名字符串和函数对象的映射存入一个字典,然后直接取出函数就能调用。

    def func_1(x, y):
        return x + y
    
    def func_2(x):
        return x*x
    
    def func_3():
        print("function 3")
    
    
    func_map = {
        "fun1" : func_1,
        "fun2" : func_2,
        "fun3" : func_3,
    }
    
    
    fun_name = "fun1"
    
    if fun_name in func_map.keys():
        func = func_map[fun_name]
        func(1,2)  # 传入参数 要根据实际的每个函数参数判断
    

    在c++中要实现这样的功能,也可以借助哈希表,将一个名字字符串和函数对象映射存入表。但是,c++的hashmap,value只能存放相同类型的变量(可以使用一些方法让容器存放不同类型的数据,但是比较麻烦)。

    函数是通过它的函数签名来唯一确定的,要想将不同的函数(返回值类型不同、或是参数个数和类型不同等)放入一个map,首先要将他们“二次封装”为具有相同“格式”的函数。

    可以使用函数指针/对象来描述一类相同的函数。如下所示,typedef int (*FunPt)(int,int); 定义了FunPt类型,它指向的是一种函数,这个函数的特点是 返回值 int, 具有两个int参数。因此,所有有这种格式的函数都可以用FunPt的指针指向。
    定义函数指针变量的语法是typedef 函数返回类型 (*名字)(参数1类型,参数2类型,...)

    #include<map>
    using namespace std;
    
    typedef int (*FunPt)(int,int);  // 定义了一种新的类型
    int fun1(int a, int b){
        return a+b;
    }
    
    int fun2(int a, int b){
        return a*b;
    }
    
    map<string, FunPt> mm = {
        {"fun1", fun1},
        {"fun2", fun2},
    };
    

    可以通过函数指针变量来指向某个函数,那么直接将所有的函数封装为具有相同格式的函数就行了。另一个问题是这些要调用的函数,它们的返回值和参数个数不一,要封装为相同格式的话,可以使用vector存放所有的参数,实际调用那个函数的时候转为相应类型。返回值可以使用封装后的返回函数返回,或者传入第二个参数,将这个参数作为实际调用产生的返回值。

    // 将相关的函数 封装为 返回bool  参数是char * 的列表 
    typedef bool (*FunPt)(vector<char *>, int&);  // 定义了一种新的类型
    int fun1(int a, int b){
        return a+b;
    }
    
    int fun2(int a){
        return a*a;
    }
    
    bool fun1_warpper(vector<char*> args, int &result){
        if (args.size() != 2){
            printf("输入参数个数不对");
            return false;
        }
        // 然后将 参数转为实际上的类型
        int a = atoi(args[0]);  
        int b = atoi(args[1]);
        result = fun1(a,b);
        return true;
    }
    
    bool fun2_warpper(vector<char*> args, int &result){
        if (args.size() != 1){
            printf("输入参数个数不对");
            return false;
        }
        // 然后将 参数转为实际上的类型
        int a = atoi(args[0]);  
        result = fun2(a);
        return true;
    }
    
    map<string, FunPt> mm = {
        {"fun1", fun1_warpper},
        {"fun2", fun2_warpper},
    };
    
    
    int main(int argc, const char* argv[]){
        auto func = mm.find("fun2");
        std::vector<char*> arg_ps;
        const char* a1 = "5";
        int result;
        arg_ps.push_back(const_cast<char*>(a1));
        func->second(arg_ps, result);
        printf("结果,result=%d",result);
    }
    

    除了使用函数指针,c++11还可以使用std::function来定义一个函数对象。它的格式也是function<返回值类型(参数1类型,参数2类型)>,通过该方法声明一个函数对象的变量。

    int fun1(int a,int b){
    
    }
    std::function<int(int, int)> func = fun1; // 然后可以使用func(a,b)调用 fun1这个函数
    
    map<string, std::function<int(int,int)>>  funcMap =
             {{ "add", fun1},  // 同时也可以把相同格式的函数存入map
              { "sub", fun2}
             };
    

    参考

  • 相关阅读:
    LNMP笔记:解决mail函数不能发送邮件
    OPENCART记录账户密码
    Nginx 0.8.5版本access.log日志分析shell命令
    几个查询信息的api接口
    chart 图表无法在显示
    RegularExpressionValidator
    用户 'WANGYACONG\ASPNET' 登录失败
    'IIS APPPOOL\ASP.NET V4.0' 登录失败
    正则表达式(转载)
    不小心删除了默认数据库的恢复方法
  • 原文地址:https://www.cnblogs.com/muyisun/p/15000022.html
Copyright © 2020-2023  润新知