我正在用C ++编写一个愚蠢的小应用程序来测试我的一个库。我希望应用程序向用户显示命令列表,允许用户键入命令,然后执行与该命令关联的操作。听起来很简单。 在C#中,我最终会编写一个列表/命令图,如下所示:
class MenuItem
{
public MenuItem(string cmd, string desc, Action action)
{
Command = cmd;
Description = desc;
Action = action;
}
public string Command { get; private set; }
public string Description { get; private set; }
public Action Action { get; private set; }
}
static void Main(string[] args)
{
var items = new List<MenuItem>();
items.Add(new MenuItem(
"add",
"Adds 1 and 2",
()=> Console.WriteLine(1+2)));
}
有关如何在C ++中实现此目的的任何建议?我真的不想为每个命令定义单独的类/函数。我可以使用Boost,但不能使用TR1。
答案 0 :(得分:6)
一种非常常见的技术是使用函数指针或boost :: function,由项目名称索引,或者使用它们的向量并按此作业的项索引进行索引。使用项目名称的简单示例:
void exit_me(); /* exits the program */
void help(); /* displays help */
std::map< std::string, boost::function<void()> > menu;
menu["exit"] = &exit_me;
menu["help"] = &help;
std::string choice;
for(;;) {
std::cout << "Please choose: \n";
std::map<std::string, boost::function<void()> >::iterator it = menu.begin();
while(it != menu.end()) {
std::cout << (it++)->first << std::endl;
}
std::cin >> choice;
if(menu.find(choice) == menu.end()) {
/* item isn't found */
continue; /* next round */
}
menu[choice](); /* executes the function */
}
C ++还没有lambda功能,所以你真的必须使用函数来完成这项任务,遗憾的是。你可以使用boost :: lambda,但请注意它只是模拟lambdas,并且远不如本机解决方案那么强大:
menu["help"] = cout << constant("This is my little program, you can use it really nicely");
注意使用constant(...),因为否则boost :: lambda不会注意到这应该是一个lambda表达式:编译器会尝试使用std :: cout输出字符串,并分配菜单[“help”]的结果(std :: ostream引用)。您仍然可以使用boost :: function,因为它将接受返回void并且不带参数的所有内容 - 包括函数对象,这就是boost :: lambda创建的内容。
如果你真的不想要单独的函数或boost :: lambda,你可以打印出项目名称的向量,然后在用户给出的项目编号上打印switch
。这可能是最简单,最直接的方式。
答案 1 :(得分:0)
为什么不将C#代码移植到C ++?还有一些工作要做,但是这样的事情应该可以完成你的大部分工作:
using std::string;
class MenuItem
{
public:
MenuItem(string cmd, string desc, boost::function<bool()> action):Command(cmd),
Description(desc),
Action(action)
{}
boost::function<bool()> GetAction() { return Action; }
string GetDescription() { return Description; }
string GetCommand() { return Command; }
private:
string Command;
string Description;
boost::function<bool()> Action;
}
通过定义,你的main()可以使用std :: list,并使用一个简单的while()循环来检查MenuItem的Action的退出值,以确定它是否应该退出。