[英]c++ std::map compare function leads to runtime "bad_function_call"
[英]C++ callback with lambda fails with bad_function_call
我對[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;
}
在這里,我通過lambda表達式中的此引用捕獲了被調用方。 但是調用test()以在調用程序內調用失敗,在運行時無法引發bad_function_call。 但是在注冊時調用回調是可行的。 知道為什么嗎? 輸出如下。
設置回調。
回調內的Callee :: callbackFunction()
Caller :: test()調用回調...
拋出'std :: bad_function_call'實例后終止調用
what():bad_function_call
讓我們看一下Callee
構造函數:
Callee(Caller c, int i) : m_i(i), caller(c) { }
在這里,您通過value傳遞Caller
,這意味着您復制對象。
因此,在main
函數變量caller
是不一樣的Callee::caller
。 main
變量caller
尚未注冊任何回調。
簡單的解決方案是使用引用 :
class Callee
{
public:
Callee(Caller& c, int i) : m_i(i), caller(c) { }
...
private:
...
Caller& caller;
};
更好的解決方案可能是重新考慮設計,您實際要解決的問題以及用例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.