好的,因为我用c ++写了很多东西已经有一段时间了,我已经习惯了更现代语言的一些细节。这是一个一直在唠叨我,我相信那里有一个答案。有没有办法在运行时调用用户指定为字符串的函数?不必诉诸某种大规模的开关/ if block?
我所处理的情况可归结为:我已经解决了我在C ++中解决的数学相关问题,并指定为“Problem1.cpp / Problem1.h”,“Problem2。 cpp / Problem2.h“等。每个问题都有一个名为problemX()
的函数(其中X
是问题的数量),它启动了解决方案。
在程序开始时,我想问用户“你想解决哪个问题?”他们指定了一个数字。然后,我想调用适当的problemX()
函数,而不必使用大量的硬编码switch语句(或if语句,或函数指针的索引数组等)。
我确信这是可能的,但我不记得该如何去做。有什么想法吗?
答案 0 :(得分:5)
unordered_map
函数指针的字符串。
调整用户输入以确保它全部为小写(或者如果您喜欢SHOUTING),则只需查找该函数。如果存在则调用它,否则错误。
答案 1 :(得分:1)
C ++没有自动编译或运行时反映其语言中的代码。许多库框架都会对库中的符号进行运行时反映。
解决方案1: 将您的问题粘贴到他们自己的动态库中,让主程序动态加载它们并查找它们导出的符号名称。
解决方案2: 用命名对象替换原始C风格的函数。所以你可能有:
class Problem;
void RegisterProblem( std::string name, Problem const* problem );
std::map< std::string, Problem const* >& GetProblems();
class Problem
{
protected:
Problem( std::string name ): RegisterProblem( std::move(name), this ) {}
virtual void operator() const = 0;
virtual ~Problem() {}
};
class Problem1: public Problem
{
public:
Problem1():Problem("Problem1") {}
virtual void operator() const { /* implementation */ }
};
// in .cpp file:
Problem1 problem1Instance();
void RegisterProblem( std::string name, Problem const* problem )
{
GetProblems()[name] = problem;
}
std::map< std::string, Problem const* >& GetProblems()
{
static std::map< std::string, Problem const* > problemMap;
return problemMap;
}
int main()
{
// parse user input to get this string:
std::string testInput = "Problem1";
// run the problem determined by testInput:
Problem* prob = GetProblems()[testInput];
Assert(prob);
(*prob)();
}
上面我们有一些可怕的代码,它们具有自注册问题(在静态映射中注册),以及执行字符串指定的任何问题的main()。
我认为更清洁的方式是:
// In RegisterProblem.h:
// these two have obvious implementations:
std::map< std::string, std::function<void()> >& GetProblems();
bool RegisterProblem( std::string s, std::function<void()> ); // always returns true
// In problem1.cpp:
void Problem1(); // implement this!
bool bProblem1Registered = RegisterProblem( "Problem1", Problem1 );
// In problem2.cpp:
void Problem2(); // implement this!
bool bProblem2Registered = RegisterProblem( "Problem2", Problem2 );
// etc
// in main.cpp:
int main(int argc, char** argv)
{
if (argc == 0)
return -1; // and maybe print help
auto it = GetProblems().find( argv[1] );
if (it == GetProblems().end())
return -1; // and maybe print help
it->second(); // call the problem
}
我们取消了不必要的类层次结构,只需在字符串和void()
函数之间维护一个映射。此映射的维护将分发到写入函数的每个位置,因此没有集中列表或if语句。
我不会发送任何代码粗糙如上所述,但我希望你明白这一点。
答案 2 :(得分:0)
您应该使用std::map<std::string,_function_pointer_defined_by_you>
将函数的名称存储为键,将函数指针存储为值。您还可以使用std::unordered_map<std::string,_function_pointer_defined_by_you>
,类似std::hash_map
。如果你可以使用C ++ 11,你会在标题文件std::unordered_map
找到<unordered_map>
,如果你不能在<tr1/unordered_map>
找到。{1}}。有关map和unordered_map的文档可以在以下位置找到: