In OO, one usually implements callbacks with interfaces: (rough example)
class Message {}
class IMsgProcessor {
public:
virtual void handle_msg(const Message& msg) = 0;
}
class RequestMsgProcessor : public IMsgProcessor {
virtual void handle_msg(const Message& msg) {
// process request message
}
}
class CustomSocket {
public:
Socket(IMsgProcessor* p) : processor_(p) {}
void receive_message_from_network(const Message& msg) {
// processor_ does implement handle_msg. Otherwise a compile time error.
// So we've got a safe design.
processor_->handle_msg(msg);
}
private:
IMsgProcessor* processor_;
}
So far so good. With C++11, another way to do this is to have CustomSocket just receive an instance of std::function object. It does not care where it is implemented or even if the object is a non-null value :
class CustomSocket {
public:
Socket(std::function<void(const Message&)>&& f) : func_(std:forward(f)) {}
void receive_message_from_network(const Message& msg) {
// unfortunately we have to do this check for every msg.
// or maybe not ...
if(func_)
func_(msg);
}
private:
std::function<void(const Message&)> func_;
}
Now here are the questions:
1. What about the performance impacts? I'm guessing a virtual function call is faster than calling a function object but how much faster? I'm implementing a fast messaging system and I'd rather avoid any unnecessary performance penalty.
2. In terms of software engineering practices, I have to say I like the second approach better. Less code, fewer files, less clutter: no interface class. More flexibility: you can only implement a subset of the interface by setting some of the function objects and leaving the others null. Or you can have different parts of the interface implemented in separate classes or by free functions or combination of both (instead of in a single subclass). Furthermore, CustomSocket can be used by any class not just subclasses of IMsgProcessor. This is a great advantage, in my opinion.
What do you say? Do you see any fundamental flaw in these argument ?
Android Callback Listeners Example:Android maintains the interaction between the end-user and the application using the widely used Listener Design Pattern. All the UI components, like a button, inherit from the View class, which in turns implements the Callback interface from android.
A callback function is a function that is passed as an argument to another function, to be “called back” at a later time. A function that accepts other functions as arguments is called a higher-order function, which contains the logic for when the callback function gets executed.
The main difference between a normal function and a callback function can be summarized as follows: A normal function is called directly, while a callback function is initially only defined. The function is only called and executed once a specific event has occurred.
In simple language, If a reference of a function is passed to another function as an argument to call it, then it will be called as a Callback function. In C, a callback function is a function that is called through a function pointer. In C++ STL, functors are also used for this purpose.
You can have the best of both worlds
template<class F>
class MsgProcessorT:public IMsgProcessor{
F f_;
public:
MsgProcessorT(F f):f_(f){}
virtual void handle_msg(const Message& msg) {
f_(msg);
}
};
template<class F>
IMsgProcessor* CreateMessageProcessor(F f){
return new MsgProcessor<T>(f);
};
Then you can either use like this
Socket s(CreateMessageProcessor([](const Message& msg){...}));
Or to make it even easier add another constructor to Socket
class Socket{
...
template<class F>
Socket(F f):processor_(CreateMessageProcessor(f){}
};
Then you could do
Socket s([](const Message& msg){...});
And still have the same efficiency as a virtual function call
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With