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

发布于 2024-07-29 20:40:52 字数 476 浏览 4 评论 0原文

  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 时,出现编译错误,提示我的参数类型不匹配,我做错了什么? 谢谢。

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

I want to bind the private member _a of Data to a member function of Display, but I get compile errors saying my argument types don't match when I call d.Register, what am I doing wrong? Thanks.

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

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

发布评论

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

评论(3

涙—继续流 2024-08-05 20:40:52

您想要做什么并不完全清楚,但我假设“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();
};

What you're trying to do is not completely clear, but I'll assume that "bind" is boost::bind (or tr1::bind).

A couple of problems with bind(Display::SomeTask, this, _1):

  • It should be &Display::SomeTask
  • The _1 placeholder makes no sense because that creates an unary function object and:
    • Display::SomeTask takes no arguments
    • Action::operator() takes no arguments

Using Boost.Function and Boost.Bind, here's what you could write to acheive what I guess you're trying to do:

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();
};
违心° 2024-08-05 20:40:52

我看不到“bind”返回什么,但我绝对确定这与 Action 类不兼容。 另外,您正在使用“复制语义”,因此如果 Action 具有空实现,您将永远不会得到想要的。
尝试更改 Register(Action* action),并允许“绑定”返回 Action 类的某些子级。

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

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

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

I cannot see what 'bind' returns, but I absolutely sure this is not compatible with Action class. Also you are using 'copy semantic', so if Action has empty implmentation, you will never get desired.
Try change Register(Action* action), and allow 'bind' to return some child of Action class.

Also review possibility to migrate to templates - than you even can exclude Action class at all

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

In this case you could be able to use as classes with overridden operator() as functions without argument.

天生の放荡 2024-08-05 20:40:52

首先,你必须使用 &Display::SomeTask 并给 Register 一个返回类型,然后根据你的需要

  • 包装器应该调用 SomeTask*this 上的 code>:省略 _1
  • 包装器应在传递的 Display 对象上调用 SomeTask:用 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();
  }

然后它应该可以工作。

First, you have to use &Display::SomeTask and give Register a return type, and then it depends on your needs

  • The wrapper should call SomeTask on *this: Omit _1.
  • The wrapper should call SomeTask on a passed Display object: Shift _1 in place of this.

Then, boost::bind returns some complicated synthesized type that will call the specified function. You need a way to store it, which is where boost::function comes handy. This is how you can do it

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

Then it should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文