C++ C++;lambda回调失败,函数调用错误

C++ C++;lambda回调失败,函数调用错误,c++,c++11,lambda,callback,C++,C++11,Lambda,Callback,我稍微修改了[1]中的回调示例,将注册移到被调用方本身,如下所示 // To build: // g++ -std=c++11 callback4.cpp #include <stdio.h> #include <functional> //------------------------------------------------------------------------ // Callback function. typedef std::funct

我稍微修改了[1]中的回调示例,将注册移到被调用方本身,如下所示

// To build:
//   g++ -std=c++11 callback4.cpp

#include <stdio.h>
#include <functional>

//------------------------------------------------------------------------
// Callback function.
typedef std::function<int(int)> CallbackFunction;

//------------------------------------------------------------------------
// "Caller" allows a callback to be connected.  It will call that callback.
class Caller
{
  public:
    // Clients can connect their callback with this.
    void connectCallback(CallbackFunction cb)
    {
      printf("setting the callback..\n");
      m_cb = cb;
      // This call works
      m_cb(10);
    }

    // Test the callback to make sure it works.
    void test()
    {
      printf("Caller::test() calling callback...\n");
      int i = m_cb(10);

      printf("Result (50): %d\n", i);
    }

private:
  // The callback provided by the client via connectCallback().
  CallbackFunction m_cb;
};

//------------------------------------------------------------------------
// "Callee" can provide a callback to Caller.
class Callee
{
  public:
    Callee(Caller c, int i) : m_i(i), caller(c) { }

    // The callback function that Caller will call.
    int callbackFunction(int i)
    {
      printf("  Callee::callbackFunction() inside callback\n");
      return m_i * i;
    }

    void registerCallback() {
      caller.connectCallback(
        [this](int i) { return this->callbackFunction(i); });
    }

private:
  // To prove "this" is indeed valid within callbackFunction().
  int m_i;
  Caller caller;
};

//------------------------------------------------------------------------

int main()
{
  Caller caller;
  Callee callee(caller, 5);

  callee.registerCallback();

  // Test the callback. This fails.
  caller.test();

  return 0;
}
//要生成:
//g++-std=c++11回调4.cpp
#包括
#包括
//------------------------------------------------------------------------
//回调函数。
typedef std::函数CallbackFunction;
//------------------------------------------------------------------------
//“调用者”允许连接回调。它将调用该回调。
类调用者
{
公众:
//客户端可以将其回调与此连接。
void connectCallback(CallbackFunction cb)
{
printf(“设置回调..\n”);
m_cb=cb;
//这个电话有效
m_cb(10);
}
//测试回调以确保其正常工作。
无效测试()
{
printf(“调用方::test()调用回调…\n”);
int i=m_cb(10);
printf(“结果(50):%d\n”,i);
}
私人:
//客户端通过connectCallback()提供的回调。
调用函数m_cb;
};
//------------------------------------------------------------------------
//“被调用方”可以向调用方提供回调。
类被叫方
{
公众:
被调用方(调用方c,int i):m_i(i),调用方(c){}
//调用者将调用的回调函数。
int callbackFunction(int i)
{
printf(“callback中的Callee::callbackFunction()”;
返回m_i*i;
}
无效注册表回调(){
caller.connectCallback(
[this](inti){返回this->callbackFunction(i);});
}
私人:
//证明“this”在callbackFunction()中确实有效。
国际货币基金组织;
呼叫者;
};
//------------------------------------------------------------------------
int main()
{
呼叫者;
被呼叫者被呼叫者(呼叫者,5);
callee.registerCallback();
//测试回调。此操作失败。
test();
返回0;
}
这里,我通过lambda表达式中的此引用捕获被调用方。但是调用test()在调用方内部调用失败,在运行时抛出错误的函数调用。但是在注册时调用回调是可行的。知道为什么吗?下面给出了输出

设置回调..
被调用方::回调内部的callbackFunction()
调用方::test()调用回调…
在抛出“std::bad_function_call”的实例后终止调用
what():错误的函数调用


[1]

让我们看看
被调用方
构造函数:

Callee(Caller c, int i) : m_i(i), caller(c) { }
在这里,您通过值传递调用方,这意味着您复制了对象

因此,在
main
函数中,变量
caller
Callee::caller
不同。
main
变量
caller
未注册任何回调

简单的解决方案是使用参考:


更好的解决方案可能是重新考虑设计,以及您实际试图解决的问题,以及有关用例的问题。

让我们看看被调用方的
构造函数:

Callee(Caller c, int i) : m_i(i), caller(c) { }
在这里,您通过值传递调用方,这意味着您复制了对象

因此,在
main
函数中,变量
caller
Callee::caller
不同。
main
变量
caller
未注册任何回调

简单的解决方案是使用参考:


更好的解决方案可能是重新考虑设计,以及您实际试图解决的问题,以及用例。

您正在修改
调用方
的副本。您正在修改
调用方
的副本。我明白了。成功了。但我能知道你为什么认为这样更好吗?你认为这种方法有什么问题吗?@chamibuddhika传递引用通常是有效的,但并不是所有情况下都可以使用引用,这会导致整个方案分崩离析。不过,这在很大程度上取决于用例,以及您实际试图用此解决方案解决的问题。我明白了。谢谢你的澄清,我明白了。成功了。但我能知道你为什么认为这样更好吗?你认为这种方法有什么问题吗?@chamibuddhika传递引用通常是有效的,但并不是所有情况下都可以使用引用,这会导致整个方案分崩离析。不过,这在很大程度上取决于用例,以及您实际试图用此解决方案解决的问题。我明白了。谢谢你的澄清。