Указатель на функцию экземпляра - PullRequest
1 голос
/ 09 июня 2011

Мне нужно сопоставить какое-то состояние определенной функции-члену класса, для (очень урезанного) примера:

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 ]

1 голос
/ 10 июня 2011

Вы можете сделать это, используя только необработанные указатели на членов:

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 Я бы, вероятно, использовал для этого связывание (из boost, tr1 или C ++ 11);это немного медленнее, но проще и гибче.

1 голос
/ 10 июня 2011

Вы должны использовать std::function или boost::function, если у вас нет поддержки C ++ 0x / TR1.Самый простой способ их использования - использовать boost::bind или std::bind, я бы не стал использовать bind1st стандарта и такой беспорядок, когда boost::bind намного лучше и проще.

1 голос
/ 09 июня 2011

Использование STL bind1st и mem_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);
      }
   }
};
0 голосов
/ 10 июня 2011

Вот рабочий пример (см. 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) ;
  }
...