在运行时获取命名空间中的函数列表?

时间:2013-05-10 14:48:27

标签: c++ function c++11 runtime function-pointers

是否可以在运行时获取某个命名空间中的函数列表或程序中的所有函数?

我有一个函数指针映射,我需要自己添加命令,但我想:为什么不创建命名空间让程序在运行时完成工作?

类似(伪代码):

typedef bool (*command)(void);
namespace Commands
{
    bool Start(void)
    {
        return true;
    }
    bool End(void)
    {
        return true;
    }
};
std::map<std::string,command> CommandMap;
main()
{
    for(each function in namespace Commands)
    {
        CommandMap[std::string(function_name)] = function;
    }
    CommandMap["Start"]();
    CommandMap["End"]();
    return 0;
}

而不是

std::map<std::string,command> CommandMap;
main()
{
    CommandMap["Start"] = Commands::Start;
    CommandMap["End"] = Commands::End;
    //list of thousands of other commands......
    CommandMap["Start"]();
    CommandMap["End"]();
    return 0;
}

这可以在C ++或C ++ 11中实现吗?或者我的目标的任何替代方案?

3 个答案:

答案 0 :(得分:3)

否(必须是30个字符)。

编辑:这与我对你有多少控制权的评论一致。您可以将所有函数重新定义为仿函数,并让构造函数将其自身注册为某个数组。你的基类看起来像这样:

EDIT2:阅读有关具有相同参数和返回类型的所有函数的注释,使其更清晰。

class myFunctorBaseClass
{
public:
    myFunctorClass () :  {//register myself, no duplicates}
    virtual int operator () (int);//Whatever types you want
};

class myFunctor: public myFunctorBaseClass  //Define as many of these as you need
{
public:

    int operator() (int y) { return y; } // Define this as whatever you want
}

这显然取决于构造的对象,但假设它们都是初始化步骤,这可以得到你想要的东西。

注意:这可能是不完整/不编译。我只是把它写在了我的头顶,但它应该是接近的。如果您对此如何运作有疑问,那么您想要的参考是“仿函数”。

答案 1 :(得分:1)

考虑类似的事情:

class CommandCollection
{
   ...
   void register_command(Command*, string);
   map<string, Command*> m_command_map;
}

class Command
{
   ...
   virtual do_command(...) = 0;
}

class EachCommand : public Command
{
   EachCommand() { CommandCollection::instance().register_command(this, my_name); }
   ...
   virtual do_command(...);
}

EachCommand each_command_inst;

Command基类有一个虚拟命令。每个派生类型都实现了命令(您可以尝试重载()运算符以使它们看起来更像函数)。 每个派生的Command都使用CommandCollection注册自身,因此可以在中心位置识别它。如果你想通过字符串关联命令(如果用户输入它们似乎很好),那么这将是地图中的关键。

答案 2 :(得分:1)

正如其他地方所提到的,名称(在C和C ++中,其他语言可能/在这一点上有所不同)仅作为源代码的一部分存在。编译后,名称在C和C ++中不再具有任何意义。

然而,人们可以考虑这样的结构:

 class CommandBase
 {
     virtual bool doCommand() = 0;
     virtual std::string name() = 0;
     virtual ~CommandBase() {}
 };

 class StartCommand : public CommandBase
 {
     bool doCommand() {  ...; return true }
     std::string name() { return "Start"; }
 };

 void RegisterCommand(CommandBase *cmd)
 {
     CommandMap[cmd->name] = cmd;
 }

 ...
 StartCommand start;
 ...
 void someFunction()
 {
    RegisterCommand(&start);
 }

我可能会因为提到宏而得到一个downvote,因为这些是邪恶的 - 如果你是一个不喜欢宏的纯粹主义者,请不要使用它。

 #define CMD(x) CommandMap[#x] = Command::x

 CMD(start);
 CMD(end);

当然还有其他变种,知道模板的人可能会想出一些使用模板来做这件事的人。