将可调用对象传递给成员函数

时间:2009-08-06 14:47:11

标签: c++ bind functor

  class Action {
    public:
      void operator() () const;
  }

  class Data {
    public:
      Data();
      ~Data();
      Register(Action action) { _a = action; }

    private:
      Action _a;
   }

  class Display {
    public:
      Display(Data d) { d.Register( bind(Display::SomeTask, this, _1) ); }
      ~Display();
      void SomeTask();
  }

我想将Data的私有成员_a绑定到Display的成员函数,但是当我调用d.Register时,我得到编译错误,说我的参数类型不匹配,我做错了什么?感谢。

3 个答案:

答案 0 :(得分:4)

你要做的事情并不完全清楚,但我会假设“bind”是boost :: bind(或tr1 :: bind)。

bind的几个问题(Display :: SomeTask,this,_1):

  • 它应该是& Display :: SomeTask
  • _1占位符没有意义,因为它创建了一元函数对象,并且:
    • Display :: SomeTask不带参数
    • Action :: operator()不带参数

使用Boost.Function和Boost.Bind,这是你可以写的,以实现我猜你想要做的事情:

typedef boost::function<void(void)> Action;

class Data {
public:
  Data();
  ~Data();
  Register(Action action) { _a = action; }

private:
  Action _a;
};

class Display {
public:
  Display(Data d) { d.Register( bind(&Display::SomeTask, this) ); }
  ~Display();
  void SomeTask();
};

答案 1 :(得分:1)

我看不出'bind'会返回什么,但我绝对相信这与Action类不兼容。你也使用'copy semantic',所以如果Action有空的implmentation,你永远不会得到你想要的。 尝试更改注册(操作*操作),并允许'bind'返回Action类的一些子项。

还要检查迁移到模板的可能性 - 甚至可以完全排除Action类

template <class A>
class Data { ...
Register(A action)...
A _a;
...

在这种情况下,您可以将具有重写的operator()的类用作没有参数的函数。

答案 2 :(得分:0)

首先,您必须使用&Display::SomeTask并为Register提供返回类型,然后这取决于您的需求

  • 包装器应在SomeTask上调用*this:忽略_1
  • 包装器应在传递的SomeTask对象上调用Display:Shift _1代替this

然后,boost::bind返回一些将调用指定函数的复杂合成类型。您需要一种方法来存储它,这是boost::function方便的地方。这就是你如何做到的

  class Display; // forward-declaration
  class Data {
    public:
      Data();
      ~Data();

      template<typename Action>
      void Register(Action action) { _a = action; }

    private:
      boost::function<void(Display&)> _a;
      // if wrapper should call it on `*this`
      // boost::function<void()> _a;
   }

  class Display {
    public:
      // this currently makes no sense. You pass a copy. Probably you
      // should consider pass-by-reference or processing "d" further. 
      Display(Data d) { d.Register( bind(&Display::SomeTask, _1) ); }
      // wrapper should call it on `*this`:
      // Display(Data d) { d.Register( bind(&Display::SomeTask, this) ); }
      ~Display();
      void SomeTask();
  }

然后它应该工作。