首页 > 解决方案 > 使用 std::bind 和 std::function 将类成员函数用作另一个类成员例程的回调

问题描述

这可能之前已经探索过,但我不确定它是如何工作的,以及在我的特定情况下应该如何......

本质上我有一个类,回调定义为:

class Foo
{
    public:
    using someCallbackName = std::function<void(int)>;
    void someFunc();
    Foo(int, someCallBackName);
    private : 
    someCallbackName m_callBack;
}

void Foo::someFunc()
{
    m_callBack(1);
}

我曾经在main()或仅通过引用类似签名的函数来调用它。

void someOtherFunction(int x)
{
    cout << x;
}

int main()
{
    Foo::someCallbackName callBack = someOtherFunction;
    Foo foo(5, callBack);
}

不过,我决定,我可能需要someOtherFunction作为班级成员,并将其作为班级的一部分。但是,使用类成员函数someOtherFunction作为回调需要将其设为静态,这可以正常工作,但这意味着它无法访问非静态类成员,这有点违背了将其放入类中的目的。

我尝试使用: 使用类成员的 C++ 回调

以及以下给出的结构访问: https ://en.cppreference.com/w/cpp/utility/functional/bind

..但它似乎不起作用, std::bind 到

Foo::someCallbackName callBack = std::bind(not_sure_what_to_use_here);

不断给出错误说没有合适的转换,这让我认为std::bind代码中的回调签名或使用机制在某处是错误的。

保持上课Foo状态,怎么能m_callBack打电话someOtherFunction

标签: c++c++11callbackstd

解决方案


您可以使用 labmda 将回调“绑定”到特定对象的非静态成员函数:

class X {
  public:
    void someOtherFunction(int x) const { std::cout << x; }
};

int main() 
  X x;
  Foo::someCallbackName callBack = [&x](int i){ x.someOtherFunction(i); };
  Foo foo(5, callBack);
  foo.someFunc();
}

现场演示:https ://wandbox.org/permlink/fUmrnD6xn1xr7zn0 。


为了避免x被销毁后的悬空引用,您可以使用共享指针,如下所示(注意它是由 value捕获的):

Foo::someCallbackName callBack;
{
  auto ptr_x = std::make_shared<X>();
  callBack = [ptr_x](int i){ ptr_x->someOtherFunction(i); };
}
Foo foo(5, callBack);
foo.someFunc();

现场演示:https ://wandbox.org/permlink/23euPcuDUsDENdRe 。


推荐阅读