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

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM