如何在 C++ 中按名称(std::string)调用函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19473313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to call a function by its name (std::string) in C++?
提问by Alan Valejo
I wonder if there is a simple way to call a function from a string. I know a simple way, using 'if' and 'else'.
我想知道是否有一种简单的方法可以从字符串中调用函数。我知道一个简单的方法,使用“if”和“else”。
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;
}
This is the basic approach
这是基本方法
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);
}
Is there something simpler?
有没有更简单的?
/* New Approach */
int callFunction(int i, int j, string function) {
/* I need something simple */
return function(i, j);
}
回答by LihO
What you have described is called reflectionand C++ doesn't support it. However you might come with some work-around, for example in this very concrete case you might use an std::map
that would map names of functions (std::string
objects) to function pointers, which in case of functions with the very same prototype could be easier than it might seem:
您所描述的称为反射,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;
}
Note that myMap[s](2,3)
retrieves the function pointer mapped to string s
and invokes this function, passing 2
and 3
to it, making the output of this example to be 5
请注意,myMap[s](2,3)
检索映射到字符串的函数指针s
并调用此函数,将2
和传递3
给它,使此示例的输出为5
回答by Martin York
Using a map of standard string to standard functions.
使用标准字符串到标准函数的映射。
#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";
}
Even better with Lambda:
使用 Lambda 效果更好:
#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";
}
回答by DarthGizka
There is another possibility which hasn't been mentioned yet, which is truereflection.
还有一种可能,还没有提到,就是真实的反映。
An option for this is accessing functions exported from an executable or a shared library using operating system functions for resolving names to addresses. This has interesting uses like loading two 'contestant' dlls into an 'umpire' program, so that people can slug it out by having their actual codes fight each other (playing Reversi or Quake, whatever).
一个选项是访问从可执行文件或共享库导出的函数,使用操作系统函数将名称解析为地址。这有一些有趣的用途,比如将两个“参赛者”dll 加载到“裁判”程序中,这样人们就可以通过让他们的实际代码相互竞争(玩黑白棋或地震,等等)来将其淘汰。
Another option is accessing the debug information created by the compiler. Under Windows this can be surprisingly easy for compilers that are compatible, since all the work can be off-loaded to system dlls or free dlls downloadable from Microsoft. Part of the functionality is already contained in the Windows API.
另一种选择是访问编译器创建的调试信息。在 Windows 下,这对于兼容的编译器来说非常容易,因为所有工作都可以卸载到系统 dll 或可从 Microsoft 下载的免费 dll。部分功能已包含在 Windows API 中。
However, that falls more into the category of Systems Programming - regardless of language - and thus it pertains to C++ only insofar as it is the Systems Programming language par excellence.
然而,这更多地属于系统编程的范畴——不管语言如何——因此它只与 C++ 相关,因为它是卓越的系统编程语言。
回答by jav
You can also put your functions into a shared library. You will load such library dynamically with dlopen() and then just make the calls to the functions with a std::string. Here an example:
您还可以将您的函数放入共享库中。您将使用 dlopen() 动态加载此类库,然后使用 std::string 调用函数。这里有一个例子:
hello.cpp
你好.cpp
#include <iostream>
extern "C" void hello() {
std::cout << "hello" << '\n';
}
main.cpp
主程序
#include <iostream>
#include <dlfcn.h>
int main() {
using std::cout;
using std::cerr;
cout << "C++ dlopen demo\n\n";
// open the library
cout << "Opening hello.so...\n";
void* handle = dlopen("./hello.so", RTLD_LAZY);
if (!handle) {
cerr << "Cannot open library: " << dlerror() << '\n';
return 1;
}
// load the symbol
cout << "Loading symbol hello...\n";
typedef void (*hello_t)();
// reset errors
dlerror();
std::string yourfunc("hello"); // Here is your function
hello_t hello = (hello_t) dlsym(handle, yourfunc.c_str());
const char *dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol 'hello': " << dlsym_error <<
'\n';
dlclose(handle);
return 1;
}
// use it to do the calculation
cout << "Calling hello...\n";
hello();
// close the library
cout << "Closing library...\n";
dlclose(handle);
}
compilation:
汇编:
g++ -fPIC -shared hello.cpp -o hello.so
and:
和:
g++ main.cpp -o main -ldl
run:
跑:
C++ dlopen demo
Opening hello.so...
Loading symbol hello...
Calling hello...
hello
Closing library...
The example was stolen from here. Thereyou can find more detailed explanation on dlopen() and c++