我正在尝试使用方法void run( string method )
来运行该类中的方法。例如:
class Foo {
public:
void run( string method ) {
// this method calls method *method* from this class
}
void bar() {
printf( "Function bar\n" );
}
void foo2() {
printf( "Function foo2\n" );
}
}
Foo foo;
int main( void ) {
foo.run( "bar" );
foo.run( "foo2" );
}
这会打印出来:
Function bar
Function foo2
谢谢! :)
答案 0 :(得分:15)
您可以创建一个std::map
,它将字符串映射到成员函数指针,只要您要调用的所有函数都具有相同的签名。
地图将被声明为:
std::map<std::string, void(Foo::*)()> function_map;
答案 1 :(得分:9)
正如其他人所指出的那样,C ++并没有开箱即用这种反思(并且可能不是你想做的事情。)
但是我会提到确实存在一些预处理器,它们为类类型和方法的子集实现了这个功能。 Qt的moc就是一个例子,它是信号/插槽机制的一部分。请注意QMetaObject ...
上的method()
和methodCount()
Qt执行此操作的方法是在构建过程中注入一个工具,该工具生成表并使用其余代码编译它们。这是你手工编写的所有内容 - 而不是语言功能。
答案 2 :(得分:6)
已经提到的地图解决方案适用于固定的函数列表,但我不认为在C ++中有一种方法可以像这样反省。也就是说,你不能有一个函数void perform( string methodName )
说“我有一个名为methodName
的方法吗?如果是,请调用它。”
答案 3 :(得分:3)
虽然之前的答案仅适用于您的解决方案,但您的解决方案看起来并不适合您的问题。
我有两个建议:1)构建一个更好的抽象基类或2)为函子(函数对象)使用基类。让我们更详细地看一下......
给定一个模拟处理器指令集的项目,我们可以用以下方式模拟执行:
struct Instruction_Interface
{
virtual void execute(void) = 0;
};
typedef std::vector<Instruction_Interface *> Instruction_Container;
//...
Instruction_Container::iterator iter;
Instruction_Container program_instructions;
//...
for (iter = program_instructions.begin();
iter != program_instructions.end();
++iter)
{
(*iter)->execute(); // Execute the instruction;
}
这允许调用每个指令的execute
方法,无论指令类型如何。可以在界面中添加更多方法;在这个例子中,可以添加“toString”,它将指令转换为文本。
Idea 2: Functors
为要使用的函数建立基类或接口。将它们放入容器中并迭代容器。迭代也可以是有条件的:
struct Functor_Interface
{
virtual std::string get_name(void) const = 0;
virtual void execute(void) = 0;
virtual void execute_if_name(const std::string& name)
{ if (name == get_name())
{
execute();
}
}
};
typedef std::vector<Functor_Interface *> Functor_Container;
//...
Functor_Container the_functors;
//...
Functor_Container::iterator iter;
for (iter = the_functors.begin();
iter != the_functors.end();
++iter)
{
(*iter)->execute_if_name("loader"); // Execute the functor if it is a *loader*.
(*iter)->execute_if_name("math");
}
总之,考虑一下你的设计,看看是否有一个更好的过程不需要函数名,而是让函数决定执行或一般执行盲方法。
答案 4 :(得分:2)
您可以创建成员函数指针的映射,映射的键是函数的名称。但是指向成员函数的指针有点难以使用。
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
更简单的方法是在run
函数中执行一堆if-then-else块来调用相应的函数。
答案 5 :(得分:1)
正如其他海报所说,你需要在C ++中手工完成,因为该语言没有内置Reflection。
C#和Java等语言都内置了这一点,因此根据您的需要,可能需要重新考虑您选择的语言。
答案 6 :(得分:1)
对于直接的C ++,上面的答案是好的。但是,一些工具包(例如,Qt)可以为C ++添加内省。这可能是一个更重的变化,而不是你想要的现有项目,但如果你正在启动一个可能需要内省的项目,那么值得搜索添加它的工具包/包装器。
答案 7 :(得分:0)
提到存在一些反映库,如CAMP:http://dev.tegesoft.com/projects/camp/apidoc/index.html
答案 8 :(得分:-3)
如果没有RTTI或某种地图,你就无法做到。或者像这样的解决方案:
class Foo { public: void run( string method ) { bar(method); foo2(method); // ... more methods here } void bar(string method) { if (method != "bar") return; printf( "Function bar\n" ); } void foo2(string method) { if (method != "foo2") return; printf( "Function foo2\n" ); } } Foo foo; int main( void ) { foo.run( 'bar' ); foo.run( 'foo2' ); }
这将为您提供您想要的相同结果