Как вызвать функцию по имени (std :: string) в C ++?

Интересно, есть ли простой способ вызвать функцию из строки? Я знаю простой способ, используя «если» и «еще».

int function_1(int i, int j) {
return i*j;
}

int function_2(int i, int j) {
return i/j;
}

...
...
...

int function_N(int i, int j) {
return i+j;
}

int main(int argc, char* argv[]) {
int i = 4, j = 2;
string function = "function_2";
cout << callFunction(i, j, function) << endl;
return 0;
}

Это основной подход

int callFunction(int i, int j, string function) {
if(function == "function_1") {
return function_1(i, j);
} else if(function == "function_2") {
return function_2(i, j);
} else if(...) {

} ...
...
...
...
return  function_1(i, j);
}

Есть ли что-то попроще?

/* New Approach */
int callFunction(int i, int j, string function) {
/* I need something simple */
return function(i, j);
}

17

Решение

То, что вы описали, называется отражение и C ++ не поддерживает это. Однако вы можете прийти с некоторым решением, например, в этом конкретном случае вы можете использовать std::map что бы сопоставить имена функций (std::string объекты), чтобы функционировать указатели, что в случае функций с тем же прототипом может быть проще, чем может показаться:

#include <iostream>
#include <map>

int add(int i, int j) { return i+j; }
int sub(int i, int j) { return i-j; }

typedef int (*FnPtr)(int, int);

int main() {
// initialization:
std::map<std::string, FnPtr> myMap;
myMap["add"] = add;
myMap["sub"] = sub;

// usage:
std::string s("add");
int res = myMap[s](2,3);
std::cout << res;
}

Обратите внимание, что myMap[s](2,3) извлекает указатель на функцию, сопоставленный со строкой s и вызывает эту функцию, передавая 2 а также 3 чтобы сделать вывод этого примера 5

42

Другие решения

Использование карты стандартной строки для стандартных функций.

#include <functional>
#include <map>
#include <string>
#include <iostream>

int add(int x, int y) {return x+y;}
int sub(int x, int y) {return x-y;}

int main()
{
std::map<std::string, std::function<int(int,int)>>  funcMap =
{{ "add", add},
{ "sub", sub}
};

std::cout << funcMap["add"](2,3) << "\n";
std::cout << funcMap["sub"](5,2) << "\n";
}

Еще лучше с лямбдой:

#include <functional>
#include <map>
#include <string>
#include <iostream>

int main()
{
std::map<std::string, std::function<int(int,int)>>  funcMap =
{{ "add", [](int x, int y){return x+y;}},
{ "sub", [](int x, int y){return x-y;}}
};

std::cout << funcMap["add"](2,3) << "\n";
std::cout << funcMap["sub"](5,2) << "\n";
}
20

Есть еще одна возможность, которая еще не была упомянута, правда отражение.

Вариант для этого — доступ к функциям, экспортированным из исполняемого файла или общей библиотеки, используя функции операционной системы для преобразования имен в адреса. У этого есть интересные применения, такие как загрузка двух «конкурирующих» библиотек в программу «судья», так что люди могут убить их, если их действительные коды будут сражаться друг с другом (играя в реверси или Quake, что угодно).

Другой вариант — доступ к отладочной информации, созданной компилятором. Под Windows это может быть удивительно легко для совместимых компиляторов, поскольку вся работа может быть выгружена в системные библиотеки или бесплатные библиотеки, загружаемые из Microsoft. Часть функциональности уже содержится в Windows API.

Однако это больше относится к категории системного программирования — независимо от языка — и, таким образом, оно относится к C ++ только постольку, поскольку он является языком системного программирования.

4
По вопросам рекламы [email protected]