Re: Avoiding pointers to member functions
Hi!
Robert Fendt wrote:
I am trying to find the best way to make part of a class's behaviour configurable during runtime, yet with as little overhead as possible. Maybe someone here has an idea? So far I have come up with 3 alternatives, all of which I do not really like for different reasons.
(1) The 'simple' solution would be to implement various alternatives of the (private) member function in question, and use a "pointer to member function" to access it. Runtime configuration can be achieved by changing the pointer value, and a function pointer should be at least as efficient as a single vtable lookup. However, I loathe function pointer syntax, and they are clumsy to use (and they IMHO hide semantics by their convoluted syntax).
Function pointers are a solution if and only if the number of possible
cases is known at the design time of your class.
Nowadays there is no much performance impact compared to switch case. If
the number of cases is larger it can be considerably faster, unless the
behavior is switched many times, because you store the (partial) result
of a decision rather than taking the decision every time anew.
(2) So, what about a functor class. It would have to be a member or friend of the outer class, and it cannot directly access the latters internals (even with 'friend' I would still have to give it a pointer to the current instance). I am also concerned about performance, since there is an additional level of indirection involved at several points when using this model.
Functors are something like user exits. They will not basically switch
functionality between a fixed number of cases. But they provide
extensibility to the user of a class instance. Of, course this is
restricted to the users permissions.
Functors have no explicit runtime overhead, since everything is done at
compile time unless you explicitly have run time code, e.g. in the
constructor. So you can control the overhead very well.
Because of this functors are often suitable in conjunction with templates.
(3) Last but not least: strict OO design, make a base class and several differently behaving child classes, and use a factory pattern to achieve at least some level of runtime flexibility. This is less flexible, so I do not really like that possibility either. Also there is the risk of duplicate code.
Inheritance is a solution if and only if the behavior of existing
objects never changes over their lifetime. The performance is comparable
to the function pointers, because the vtable calls are similar to
function pointers.
But if your behavior is constant over object lifetime there is another
solution. As cr88192 already said you can combine 2 and 3. And if you
use a template base class which takes the functors as template arguments
you will end up with no runtime overhead.
However, the same will happen with an optimizing compiler, if you pass
an enumeration type as template argument to your class to switch the
behavior and use switch/case again. If you do not like the resulting
long type names, feel free to use typedefs and end up with the same type
names as with (3). Of course, the additional restriction of limited
cases applies here.
Marcel