Q1. Why are callback functions used?
Q2. Are callbacks evil? Fun for those who know, for others a nightmare.
Q3. Any alternative to
Q3. Any alternative to callback?
I prefer the functor form of callback. e.g. this sort of thing:
class WidgetContainerOrProcessorOfSomeSort
{
public:
struct IWidgetFunctor
{
virtual bool operator()( const Widget& thisWidget )=0;
};
....
bool ProcessWidgets( IWidgetFunctor& callback )
{
.....
bool continueIteration = callback( widget[ idxWidget ] );
if ( !continueIteration ) return false;
.....
}
};
struct ShowWidgets : public WidgetContainerOrProcessorOfSomeSort::IWidgetFunctor
{
virtual bool operator(){ const Widget& thisWidget }
{
thisWidget.print();
return true;
}
};
WidgetContainterOrProcessorOfSomeSort wc;
wc.ProcessWidgets( ShowWidgets() );
It always seems a bit verbose for simple samples, but in the real world I find it much easier than trying to remember exactly how to construct complex function pointer declarations :-)
Regardless of "using callbacks in C++ increase coupling" or not, I suggest using event handler style especially process event-like things. For example, concrete a Design Pattern instead of callback concept as the below:
class MyClass
{
public:
virtual bool OnClick(...) = 0;
virtual bool OnKey(...) = 0;
virtual bool OnTimer(...) = 0;
virtual bool OnSorting(...) = 0
...
};
You may still consider the above functions are callbacks, but when considering them as the known Design Pattern, you won't get confused because you are doing OO and writing C++.
Effo UPD@2009nov13 - Typical cases: Framework, Events System or Concurrent Programming Model, and so on. Following examples should be useful.
Framework controls the overall flow as the Hollywood Principle states "Don't call us, we'll call you." (that's what "callback" means exactly) while per a normal function or lib, caller controls the flow.
A well-known C framework is Linux kernel and a Linux driver writer knows that s/he'd implement a "struct file_operations" in it "read()" means OnRead() and "write()" means OnWrite() etc.
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
...
};
But the simplest example of a framework should be:
The Framework | A developer to do
----------------------------+--------------------------------------
| class MyClass : public Actor
| {
| public:
pApplication->Init(...); | virtual bool OnInit(...) {}
pApplication->Run(...); | virtual int OnRun(...) {}
pApplication->Quit(...); | virtual void OnQuit(...) {}
| ...
| };
and pApplication->Init() will call pActor->OnInit, and pApplication->Run() calls pActor->OnRun(), and so on internally. Most Windows GUI developers had experienced implementing OnMouseClick() or OnButtonPress() etc.
I agree with other answers of this thread that they give correct explanation based on the viewpoint accordingly, such as handlers in layered approach, generalized callback or aynchronous operations, and so on. It's up to you that what idea(s) would be suitable for you.