Search code examples
c++function-pointersobserver-pattern

C++, functions pointers vs observer pattern


Years ago before I knew much about C++ I was talking to an experienced programmer colleague about creating event systems etc. He seemed to put emphasis on the need to pass function pointers around so that callbacks could be made to notify classes of state changes etc.

However, these days whenever I need to implement some kind of event system I simply construct a pseudo interface class, inherit from it and use the subscriber/observer pattern to override the methods and distribute events.

I was thinking the other day that thus far, I've rarely needed to use function pointers, certainly not for the above kind of situation. The one and only situation where I really had to use function pointers was when interfacing with someone else's .dll that explicitly required one to be passed.

When should I be using function pointers instead of the subscriber/observer pattern?

Is it good/bad practice to use one or the other? (presumably there must be instances where the observer pattern isn't better than a function pointer).

Please could someone share some insight? It would be good to get some more experience on this? (Aforementioned colleague has moved onto another business and we've lost contact). I keep racking my brain over this subject and can't think of when it wouldn't be neater to use the observer pattern and an interface.

Thanks!

Example of a class I'd often find myself writing (Written without testing, completely off the top of my head, might not actually work):

class NotifierListener {

friend class Notifier;
private:
vector<NotifierListener*> mListeners;

protected:
void subscribe(NotifierListener* _subscriber) {mListeners->push_back(_subscriber);}
virtual void onNotification();
}

class Notifier : public NotifierListener {

private:
void doSomethingAndNotify() {

...
if (mListeners.size() > 0) {
for (int i = 0; i < mListeners.size(); ++i) {

mListeners[i]->onNotification();
}
}

}
}

class Something : public NotifierListener {

Something() { subscribe(this); }

void onNotification() {

cout << "I got notified\n" << endl;
}
}

Solution

  • Function pointers are a bit more efficient. You now pass a pointer to an interface. The interface typically* contains a pointer to a vtable. And that vtable in turn contains function pointers. That's 3 levels of indirection, with poor locality of reference.

    [*] Other implementations are possible, but have similar overhead.