1

对于我的大学作业,我需要为基于函数(或命令)的语言制作 C++ 解释器。解释器必须读取输入文件,提取单词(字符串),生成命令并执行它们。所有命令都是继承自一个公共超类(Command例如 )的类,它有一个名为 的虚拟方法execute。对于从输入文件中读取的每个单词,都会创建一个命令并将其存储在vector<Command>.

所以,我正在考虑使用一个哈希表,它的键是命令的名称(字符串),它的值是某种允许我创建特定类的对象(或者让我访问特定类的构造函数),轻松地为每个单词创建类,而不是使用 if-else-if 链。

到现在为止,我正计划创建一个CommandGenerator类,它调用generate一个返回一个新Command对象的虚方法。我的命令哈希表的值将是CommandGenerator该类的对象。所以我从它派生了所有命令的许多其他子类,它们返回从Command.

但是,这样的东西已经存在了吗?或者有没有更优雅的方式来做到这一点?是否可以从类中提取任何类型的对象来表示它?

4

2 回答 2

1

如果每个命令都是 的子类Command,为什么不使用 astd::vector<Command*>并将指针推送到每个子类的实例?然后你可以遍历向量并调用你的虚execute函数。

在向量中放置类最接近的方法是boost::fusion::vector. 但不能在运行时填写,对您的具体情况没有用处。


假设您可以使用 C++11。如果您可以将命令定义为一个execute函数,您可以执行以下操作:

map<string, function<void()>> cmds = {
    make_pair("print1", [](){
        cout << "1" << end;
    }),
    make_pair("print2", [](){
        cout << "2" << end;
    }),
    make_pair("print3", [](){
        cout << "3" << end;
    })
};

然后将命令放在一个向量上:

vector<function<void()>> list;
list.push_back(cmds["print1"]);
list.push_back(cmds["print1"]);
list.push_back(cmds["print2"]);

然后只需执行一个循环:

for (function<void()>& cmd : list)
    cmd();

这应该打印112到屏幕上。但是,如果您非常关心速度,请改用大量 ifs。

于 2012-12-15T17:12:55.680 回答
1

您遇到的基本问题是:您将类的名称作为字符串,并希望使用该名称创建一个类。就像您提到的那样,您必须以某种方式手动进行此翻译。这已经在这里讨论过好几次了,比如在使用工厂模式按名称实例化类中或在寻找更好的 C++ 类工厂中。我要在这里做的唯一补充:使用好的旧宏,因为它们有一个字符串化操作符。例如:

#include <stdio.h>
#define CREATEOBJ(clss,command) if (strcmp (#clss, command)==0) return new clss;
class Base {
public:
  virtual const char *name()=0;
};
class A : public Base {
public:
  const char *name() {return "I am an A";}
};
class B : public Base {
public:
  const char *name() {return "I am an B";}
};
Base *makeInstance (const char *nm) {
  CREATEOBJ(A,nm);
  CREATEOBJ(B,nm);
}
int main () {
  printf ("%s\n", makeInstance ("A")->name());
  printf ("%s\n", makeInstance ("B")->name());
}

当然,您可以通过使用包含字符串和一些函数指针或生成器类指针的哈希表使其变得更好,但想法保持不变:添加一个新类,只需再添加一个 CREATEOBJ-thingy。

于 2012-12-15T17:23:29.347 回答