2

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

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

类似(伪代码):

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 中实现吗?或者我的目标的任何替代方案?

4

3 回答 3

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
}

这显然取决于正在构造的对象,但假设它们都作为初始化步骤,这将得到你想要的。

注意:这可能不完整/未编译。我只是在脑海中写下了这个,但它应该很接近。如果您对它的工作原理有疑问,您想要的参考是“函子”。

于 2013-05-10T14:50:27.417 回答
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 基类有一个 virtual 来执行命令。每个派生类型都实现了命令(您可以尝试重载 () 运算符以使它们看起来更像函数)。每个派生的命令都向 CommandCollection 注册自己,因此可以在中心位置知道它。如果您想通过字符串关联命令(如果用户正在输入它们似乎很好),那么这将是地图中的关键。

于 2013-05-10T15:08:42.347 回答
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);
 }

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

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

 CMD(start);
 CMD(end);

当然还有其他变体,知道模板的人很可能会想出一些使用模板来做到这一点的东西。

于 2013-05-10T15:19:42.803 回答