Reputation: 2691
I realise this is a newbie question, but as I'm trying to learn C++ I'm stumpling upon this expression "callback" frequently. I've googled it and checked wikipedia, but without finding a good explination. I am familiar with some Java and C#, but how unlikely it sounds, I have never really understood what a callback means.
If someone know how to explain this term to a simple layman, I would be really thankfull.
Upvotes: 10
Views: 6643
Reputation: 29229
I posted this answer for another question, but it seems to be just as applicable here.
Here are ways to implement callbacks in C++ from (roughly) most flexible to least:
Several signals and slots implementations are listed here (notably Boost.Signal). These are useful to implement the Observer design pattern where more than one object is interested in receiving notifications.
You can register a boost::function
callback. boost::function
is wrapper around any callable entity: free function, static function, member function, or function object. To wrap a member function, you use boost::bind
as shown in this example. Usage example:
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
typedef boost::function<void (void)> MouseCallback;
class Mouse
{
public:
void registerCallback(MouseCallback callback) {callback_ = callback;}
void notifyClicked() {if (callback_) callback_();}
private:
MouseCallback callback_;
};
class Foo
{
public:
void mouseClicked() {std::cout << "Mouse clicked!";}
};
int main()
{
Mouse mouse;
Foo foo;
mouse.registerCallback(boost::bind(&Foo::mouseClicked, &foo));
mouse.notifyClicked();
}
There is a delegate implementation, called FastDelegate that is faster than boost::function
. It uses an "ugly hack" that is not supported by the C++ standard, but is supported by practically all compilers.
There is also The Impossibly Fast C++ Delegates that is supported by the standard, but not by all compilers.
You can register a pointer to an object derived from a callback interface (abstract class). This is the traditional Java way of doing callbacks. Example:
class MouseInputListener
{
public:
virtual void mouseClicked() = 0;
virtual void mouseReleased() = 0;
};
class Mouse
{
public:
Mouse() : listener_(0) {}
void registerListener(MouseInputListener* listener) {listener_ = listener;}
void notifyClicked() {if (listener_) listener_->mouseClicked();}
void notifyReleased() {if (listener_) listener_->mouseReleased();}
private:
MouseInputListener* listener_;
};
class Foo : public MouseInputListener
{
public:
virtual void mouseClicked() {cout << "Mouse clicked!";}
virtual void mouseReleased() {cout << "Mouse released!";}
};
You register a pointer to a callback free function, plus an additional "context" void pointer. In the callback function, you cast the void*
to the object type that will handle the event, and invoke the proper method. For example:
typedef void (*MouseCallback)(void* context); // Callback function pointer type
class Mouse
{
public:
Mouse() : callback_(0), context_(0) {}
void registerCallback(MouseCallback callback, void* context = 0)
{callback_ = callback; context_ = context;}
void notifyClicked() {if (callback_) callback_(context_);}
private:
MouseCallback callback_;
void* context_;
};
class Foo
{
public:
void mouseClicked() {cout << "Mouse clicked!";}
static void callback(void* context)
{static_cast<Foo*>(context)->mouseClicked();}
};
int main()
{
Mouse mouse;
Foo foo;
mouse.registerCallback(&Foo::callback, &foo);
mouse.notifyClicked();
}
I have found some performance benchmarks:
They should give you an idea of what callback mechanism is appropriate for different performance requirements.
As can be seen by the numbers, Boost signals would have to be invoked 10,000 to 100,000 of times per second before performance even becomes an issue.
Upvotes: 0
Reputation: 1716
in C++ check out boost::function
http://www.boost.org/doc/libs/1_39_0/doc/html/function.html
Upvotes: 0
Reputation: 85665
I am familiar with some Java and C#
A callback is an event or delegate in those languages - a way to get your code run by somebody else's code in it's context. Hence, the term "callback":
A canonical example is a sort routine with a user defined comparison function (the callback). Given a sort routine such as:
void Sort(void* values, int length, int valueSize,
int (*compare)(const void*, const void*)
{
for (int i = 0; i < length; i = i + 2) {
// call the callback to determine order
int isHigher = compare(values[i], values[i + 1]);
/* Sort */
}
}
(The specifics of how the sort is performed isn't important - just focus on the fact that any sorting algorithm needs to compare 2 values and determine which is higher.)
So, now we can define some comparison functions:
int CompareInts(const void* o, const void* p) {
int* a = (int*) o;
int* b = (int*) p;
if (a == b) return 0;
return (a < b) ? -1 : 1;
}
int ComparePersons(const void* o, const void* p) {
Person* a = (Person*) o;
Person* b = (Person*) p;
if (a == b) return 0;
return (a->Value() < b=>Value()) ? -1 : 1;
}
And reuse the same sort function with them:
int intValues[10];
Person personValues[10];
Sort(intValues, 10, sizeof(intVaues[0]), CompareInts);
Sort(personValues, 10, sizeof(personVaues[0]), ComparePersons);
Things get a bit more complicated if you're using member functions, as you have to manage the this
pointer - but the concept is the same. As with most things, it's easier to explain them in C first. ;)
Upvotes: 16
Reputation: 80859
A callback is a hook into the code that is executing to allow you to provide customised features at known points in the process. It allows for generalised control structures to perform customised operations which are specified by your code which is called from within them, hence the term "call back" - it calls back into your code.
Generally this is done by you providing a function pointer with a specific pre-defined signature and the generic code doing the call back will pass parameters to your function and expect a return value of a certain type.
It is a really powerful pattern which allows for code re-use and quite simple customisation/extension without completely re-writing.
Custom sort functions are a great example. The sort algorithm is generic, the comparison function is specific to what is being sorted. Many algorithms allow you to provide a function which takes two arguments of generic types, being the objects to compare, and expects you to return a +ve, -ve or zero value depending on the result of the compare.
You then write the comaprison function yourself and provide a function pointer to the sort algorithm which it "calls back" during sorting.
Upvotes: 3
Reputation: 4815
In the simplest terms a callback is a code that you pass into another method.
E.g. you have a class A which calls a method on class B but you need some code running from Class A when it's finished. You put your code in its own new method on class A and you pass the method name in when you call the method on class B. When the method on class B has done its stuff it can 'call back' into class A.
Nowadays, you don't actually need to put the callback code in its own method: you've got anonymous methods and lambda expressions you can use. I think it's probably least confusing (at least, in C#) to learn using anonymous methods until you get it.
Good luck!
P.S. I was the same: I was coding C# for years before I really understood them.
Upvotes: 2
Reputation: 124335
When you send something a callback, you send it a way of addressing a function (for example, a function pointer in C++) so that the code you're sending it to can call that function later, when it's completed some process.
The difference between
start_some_process(some_value, some_function()) # not using a callback
and
start_some_process(some_value, some_function) # using a callback
is that in the first instance you're sending the result of the function, while in the second instance you're sending the function itself.
Upvotes: 5