指向实例成员的函数指针

发布于 2024-11-14 11:22:46 字数 554 浏览 2 评论 0原文

我需要将某些状态映射到类的特定成员函数,例如:

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 的东西,但不知道如何使用。

是的,我可以用一百零一种不同的方式来做到这一点,但我想弄清楚这种方式是否可行。

I need to map some state to a particular member function of a class, for (a very cut down) example:

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);
      }
   }
}

Using just the STL (can't use third party stuff like boost), What is the type of _a_ptr_to_some_member and how do I bind the method UpdateGuiForStopState to it?

Presumably I use the stl mem_xxx stuff but can't work out how.

And yes I can do this a hundred and one other different ways, but I want to work out if this way is possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

樱娆 2024-11-21 11:22:46

使用 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);
      }
   }
};

Using STL's bind1st and 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);
      }
   }
};
秋日私语 2024-11-21 11:22:46

您可以仅使用指向成员的原始指针来完成此操作:

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 的一个实例 - 在本例中是 this 所指向的实例。我认为额外的括号是需要的;运算符优先级有点奇怪。

老实说,我可能会为此使用绑定(来自 boost、tr1 或 C++11);它稍微慢一些,但更容易、更灵活。

You can do this using just raw pointers to members:

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

That's a bit old school these days, and the syntax is a bit hairy, but it should work. (Caveat: I haven't tried it.)

The first bit defines the correct type of pointer to a member function and declares a member variable of that type.

The second bit initialises _p to point to the correct function (you can't shorten this, that's the required syntax).

The third bit calls the member function pointed to by _p; to do that you have to supply an instance of Z - in this case the one pointed to by this. I think the extra parenthese are needed; the operator precedence is a bit weird.

TBH I'd probably use bind (from boost, tr1, or C++11) for this; it's very slightly slower, but easier and more flexible.

还在原地等你 2024-11-21 11:22:46

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

You should use a std::function, or, boost::function if you don't have C++0x/TR1 support. The easiest way to use them would be using boost::bind or std::bind, I wouldn't use the Standard's bind1st and such mess when boost::bind is much better and easier.

唐婉 2024-11-21 11:22:46

这是一个工作示例(请参阅 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) ;
  }

Here is a working example (see 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) ;
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文