derive versus functor

A functor is a callback, ie: a function pointer with some stored arguments to which other arguments are attached at time of invocation.

A virtual function is one which is called indirect through a table of function pointers that is built by the compiler+linker, and pointed to by each derived class object.

Overloading a virtual function in a derived class causes all members of that derived class to share the same function call.
Using a functor instead of a virtual function allows each member of the nominally derived class to have independent behavior at the point that the function is called. The sigc library (and presumably Boost has similar abilities) have convenient syntax for having a list of functors operated upon and invoked as if it were a single function pointer.

Even if all members of a derived class are to use the same actual function at some calling point the functor approach still has an advantage: the caller does not need any scope to the store arguments of the functor. This can greatly speed up compilation. On the other hand invoking a functor is usually much more expensive in execution time than a virtual function (which is only slightly slower than a compile-time resolved function call). The functor invocation must mix its stored and point-of-call arguments into the stack frame before the function is actually called. The sigc library usually does at least 6 function calls, many indirect through simple function pointers, before the actual ‘payload’ function is called.

The functor also has the risk that any pointer/reference arguments will point to objects that get deleted/freed without the functor being invalidated. Sigc library handles this invalidation via a base class sigc::trackable which maintains a list of pointers to functors that have references to the sigc::trackable object.


Conclusion:
Use normal derived class/virtual function technology whenever speed or data size are issues. You can mix the two in some cases via having instances of normal virtual function override for many derived class, and also have a derived class whose override calls a functor.

Leave a comment