Reputation: 65
I am in a position to choose between function pointers and subclassed objects. To make it clear, say I have to notify some object of some action (a timer for example); refer to the following two choices (a very basic code for demo purposes):
Version 1
typedef void TimerCallback(void *args);
class Timer{
public:
Timer();
~Timer();
void schedule(TimerCallback *callback, void *args, long timeout)=0;
void cancel();
};
Version 2
class TimerTask{
public:
TimerTask();
virtual ~TimerTask();
void timedout()=0;
};
class Timer{
public:
Timer();
virtual ~Timer();
void schedule(TimerTask *callback, long timeout)=0;
void cancel();
};
which one is the standard C++ way and which one is efficient? Please let me know if you have any other suggestions in this regard.
Please let me know if I am not clear in this regard.
Thanks
Upvotes: 4
Views: 669
Reputation: 409166
I would say std::function
and std::bind
. Then it doesn't matter if you want to use inherited classes, standalone functions, member functions or lambdas.
By the way, if anyone is curious I made a simple timer event handling some time ago, as an answer to another question. It's showcasing the use of e.g. std::function
and std::bind
: https://stackoverflow.com/a/11866539/440558.
Upvotes: 14
Reputation: 25927
Function pointer effectively prevents you to use closures - assigning methods to you event handler (This is not entirely true, but it will restrict you in such way, that this solution is not much of a use).
I would vote on object-oriented approach. If you use C++11, you may simplify your code a lot:
#include <cstdio>
#include <functional>
class Emitter
{
private:
std::function<void(int)> eventHandler;
public:
void SetEventHandler(std::function<void(int)> newEventHandler)
{
eventHandler = newEventHandler;
}
void EmitEvent()
{
eventHandler(42); // + error-checking
}
};
class Handler
{
private:
void HandleEvent(int i)
{
printf("Event handled with i == %d\n", i);
}
public:
void AttachEmitter(Emitter & e)
{
e.SetEventHandler([this](int i) { HandleEvent(i); });
}
};
int main(int argc, char * argv[])
{
Emitter e;
Handler h;
h.AttachEmitter(e);
e.EmitEvent();
}
Upvotes: 1
Reputation: 950
Both work. Your first one is "C style" and will require a static function somewhere. The second version is "C++ style" and allows you to use an instance of TimerTask.
Generally, version 2 should be used because it removes the need for a static function.
Upvotes: 0
Reputation: 4184
I think it's better to use boost(or std since C++11)::function
to hold callback and boost::bind
to bind it's arguments, or to use boost::signal
.
That would be more general and verbose solution at cost of really small penalty.
http://www.boost.org/doc/libs/1_53_0/doc/html/signals2.html
Upvotes: 4
Reputation: 22241
You are using object-oriented programming and you should follow the object-oriented programming paradigms.
In my opinion using objects, not function pointers, is the cleaner and generally better way to do.
You can also attempt to use a visitor pattern to make the code even better and more flexible.
You can also consider publisher/subscriber pattern.
Upvotes: 2