C++ 使用boostbind/function创建菜单处理程序

C++ 使用boostbind/function创建菜单处理程序,c++,boost-bind,C++,Boost Bind,我想创建一个菜单处理程序来替换如下构造: void MyClass::handleMenu(MenuID id) { switch (id) { case option1: doFunction1(); break; case option2: doFunction2(true); break; case option3: memberVariable->doOtherFunction(); break; } } 随着菜单项数量的增加,switch语

我想创建一个菜单处理程序来替换如下构造:

void MyClass::handleMenu(MenuID id) {
  switch (id) {
    case option1:  doFunction1(); break;
    case option2:  doFunction2(true); break;
    case option3:  memberVariable->doOtherFunction(); break;
  }
}
随着菜单项数量的增加,switch语句也会增加,因此我想切换到一种机制,在这种机制中,菜单设置有许多函数对象,这些函数对象是响应菜单通知而调用的。有些函数可能采用其他参数(在设置时已知),有些函数可能是对成员函数的调用

我觉得应该是这样的:

 void MyClass::setupMenu() {
   std::map<MenuID, boost::function<void()>>  idMap;
   idMap[option1] = boost::bind(&MyClass::doFunction1, _1, this);
   idMap[option2] = boost::bind(&MyClass::doFunction2, _1, this, true);
   idMap[option3] = boost::bind(&MemberClass::doOtherFunction, _1, memberVariable);
 }

 void MyClass::handleMenu(MenuID id) {
   auto f=idMap[id];
   f(); // invoke callback     
 }
void MyClass::setupMenu(){
std::map-idMap;
idMap[option1]=boost::bind(&MyClass::doFunction1,_1,this);
idMap[option2]=boost::bind(&MyClass::doFunction2,_1,this,true);
idMap[option3]=boost::bind(&MemberClass::doOtherFunction,_1,memberVariable);
}
void MyClass::handleMenu(菜单id){
自动f=idMap[id];
f();//调用回调
}
但是,我无法获得
boost::function
类型和
bind
调用的正确组合。有些函数可能会返回一个值,这可能会使问题变得复杂,但在菜单处理代码中,我们不关心这一点,我们可以将其视为void。编译器错误往往出现在将
bind
的结果插入映射的调用中。我是否错过了一个更简单的方法

编辑:


@弗兰克的方法奏效了,但是我发现了一个我没有预料到的问题:如果您试图在调试器中单步执行代码,以找到由菜单项执行的函数,那么这是相当困难的,因为在进行实际函数调用之前,您必须在
boost::bind
代码的多个层中进进出出。很遗憾,调试器没有跟上Boost和Tr1的出血边缘。

< P>一个C++成员函数作为这个指针的第一个参数。

bind使函数对象形成函数指针及其传递的参数。_1,_2。。。是占位符(lambdas)。调用函数对象时将传递它们

class MyClass{
  /// Callback signature for calling the function for a specific command.
  typedef boost::function<void ()> TMenuCmdCallback;
  int doFunction1(bool);
  void doFunction2();
  double doFunction3(int);
  void setupMenu(){
    TMenuCmdCallback callback;
    m_Callbacks[ 1] = boost::bind(&MyClass::doFunction1, this, true);  // allways pass true
    m_Callbacks[10] = boost::bind(&MyClass::doFunction1, this, false); // allways pass false
    m_Callbacks[ 2] = boost::bind(&MyClass::doFunction2, this);
    m_Callbacks[ 3] = boost::bind(&MyClass::doFunction3, this, this->m_Int);
  }
  void callFunction(int index)
  {
    m_Callbacks[index]();
  }
  std::map<int, TMenuCmdCallback> m_Callbacks;
  int m_Int;
};
class-MyClass{
///用于为特定命令调用函数的回调签名。
typedef boost::函数TMenuCmdCallback;
int-doFunction1(bool);
void doFunction2();
双do3(int);
无效设置菜单(){
TMenuCmdCallback;
m_回调[1]=boost::bind(&MyClass::doFunction1,this,true);//始终传递true
m_回调[10]=boost::bind(&MyClass::doFunction1,this,false);//始终传递false
m_回调[2]=boost::bind(&MyClass::doFunction2,this);
m_回调[3]=boost::bind(&MyClass::doFunction3,this,this->m_Int);
}
void callFunction(int索引)
{
m_回调[索引]();
}
std::map m_回调;
int m_int;
};
在我的示例中,我不检查索引是否超出范围。 在本例中,我也不需要lambda,因为在运行时(在callFunction中),我没有要传递的参数


我不确定函数3的回调是否真的有效(但它至少可以编译)。

删除
\u 1
。它们将代表(至少)使用1个参数的函数。您的定义idMap没有使用任何参数。实际上,可以使用
mem\u-fun
(或
mem\u-fn
)进行简化吗?当然只有
doFunction2
与这里的回调签名匹配?@Moo Juice:
boost::bind
提供了要使用的所有参数,以便以后可以在没有参数的情况下调用回调。请注意,绑定到
this->m_Int
将传递调用
setupMenu()
时的值
m_Int
。如果您想在回调时获得
m_Int
的值,请尝试绑定
boost::ref(m_Int)
。@aschepler,啊,我理解。我成功地使用了与此非常类似的代码(我不确定是什么原因导致它以前失败)。请参阅我的编辑,了解我刚刚意识到的缺点。