Reputation: 1439
I slightly modified the callback example found at [1] to move the registration in to the callee itself as follows.
// 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;
}
Here I capture the Callee by this reference in the lambda expression. But the call to test() to invoke within Caller failes throwing a bad_function_call at runtime. But calling the callback at registration time works. Any idea why that is? The output is given below.
setting the callback..
Callee::callbackFunction() inside callback
Caller::test() calling callback...
terminate called after throwing an instance of 'std::bad_function_call'
what(): bad_function_call
[1] http://tedfelix.com/software/c++-callbacks.html
Upvotes: 0
Views: 1857
Reputation: 409146
Lets take a look at the Callee
constructor:
Callee(Caller c, int i) : m_i(i), caller(c) { }
Here you pass Caller
by value, meaning you copy the object.
So in the main
function the variable caller
is not the same as Callee::caller
. The main
variablecaller
have not had any callback registered.
The easy solution is to use references:
class Callee
{
public:
Callee(Caller& c, int i) : m_i(i), caller(c) { }
...
private:
...
Caller& caller;
};
A better solution might be to rethink the design, and what problem you are actually trying to solve, and about the use-cases.
Upvotes: 3