指向实例成员的函数指针

时间:2011-06-09 17:18:35

标签: c++ stl function-pointers

我需要将一些状态映射到一个类的特定成员函数,用于(非常简化)示例:

class Z {
   _a_ptr_to_some_member _p;

   void UpdateGuiForStopState(State s) {
      // do something with state
   }

   Z() {
      // setup _p to point to UpdateGuiForStopState
   }

   void StateComesInHere(State s) {
      if(s.id == STOP_ID) { // eventually use lookup
         _p(s);
      }
   }
}

仅使用STL(不能使用像boost这样的第三方内容),_a_ptr_to_some_member的类型是什么,如何将方法UpdateGuiForStopState绑定到它?

据推测,我使用的是stl mem_xxx,但无法解决问题。

是的,我可以用一百种不同的方式做到这一点,但如果可行的话,我想解决这个问题。

4 个答案:

答案 0 :(得分:1)

使用STL的bind1stmem_fun

class Z3 {
   typedef std::mem_fun1_t<void,Z3,State> _a_ptr_to_some_member_raw;
   typedef std::binder1st<_a_ptr_to_some_member_raw> _a_ptr_to_some_member;
   _a_ptr_to_some_member _p;

   void UpdateGuiForStopState(State s) {
      // do something with state
   }

   Z3() : _p(std::bind1st(std::mem_fun(&Z3::UpdateGuiForStopState), this))
   {
   }

   void StateComesInHere(State s) {
      if(s.id == STOP_ID) { // eventually use lookup
         _p(s);
      }
   }
};

答案 1 :(得分:1)

您只需使用指向成员的原始指针即可完成此操作:

typedef void (Z::*_a_ptr_to_some_member)(State s);
_a_ptr_to_some_member _p;
...
_p = &Z::UpdateGuiForStopState;
...
(this->*_p)(s);

这些天有点老派,语法有点毛茸茸,但应该有用。 (警告:我没试过。)

第一位定义了指向成员函数的正确指针类型,并声明了该类型的成员变量。

第二位初始化_p指向正确的函数(你不能缩短它,这是必需的语法)。

第三位调用_p指向的成员函数;要做到这一点,你必须提供一个Z的实例 - 在这种情况下,这是一个指向的实例。我认为需要额外的括号;运算符优先级有点奇怪。

TBH我可能会使用bind(来自boost,tr1或C ++ 11);它的速度稍慢,但更容易,也更灵活。

答案 2 :(得分:1)

如果您没有C ++ 0x / TR1支持,则应使用std::functionboost::function。使用它们的最简单方法是使用boost::bindstd::bind,我不会使用标准版bind1st,并且当boost::bind变得更好更容易时会出现这种混乱。

答案 3 :(得分:0)

以下是一个工作示例(请参阅http://ideone.com/VEmRZ):

#include <iostream>

typedef enum { s0, s1, s2 } State ;

class Z {
public:
  void f0 (State s) { std::cout << "f0" << std::endl ; }
  void f1 (State s) { std::cout << "f1" << std::endl ; }
} ;

typedef void (Z::*_a_ptr_to_some_member)(State s);

int main()
  {
  Z z ;
  _a_ptr_to_some_member _p = &Z::f0 ;
  (z.*_p)(s0) ;
  _p = &Z::f1 ;
  (z.*_p)(s2) ;
  }