Well, you can rewrite for loops to use iterators and more STLs, for example:
void foo() { std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(&Small::foo)); } void bar() { std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(&Small::bar)); }
Other than that, you can use some macros to avoid multiple redialing, but I'm not a big fan of this. Personally, I like several functions on one that accepts the command line. As it gives you more flexibility as to how the decision is made.
If you go with one function that takes a parameter to decide what to do, I would use an enumeration and a switch like this, it would be more efficient than strings and cascading ifs. In addition, in your example, you have an if to decide what to do inside the loop. It is more efficient to check outside the loop and have redundant copies of the loop, since “which command” should be defined only once per call. (NOTE: you can make a command a template parameter if it is known at compile time, which sounds as it is).
class Big { public: enum Command { DO_FOO, DO_BAR }; void doit(Command cmd) { switch(cmd) { case DO_FOO: std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(&Small::foo)); break; case DO_BAR: std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(&Small::bar)); break; } };
In addition, as you already mentioned, it’s quite simple to replace the & Small :: whatever symbol with that pointer to a member function and just pass it as a parameter. You can even create a template.
class Big { public: template<void (Small::*fn)()> void doit() { std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(fn)); } };
Then you can do:
Big b; b.doit<&Small::foo>(); b.doit<&Small::bar>();
The good thing about this and regular parameter methods is that Big doesn't need to be changed if you change small to have more routines! I think this is the preferred method.
If you want to be able to handle one parameter, you also need to add bind2nd, here is a complete example:
#include <algorithm> #include <functional> #include <iostream> #include <vector> class Small { public: void foo() { std::cout << "foo" << std::endl; } void bar(int x) { std::cout << "bar" << std::endl; } }; class Big { public: template<void (Small::*fn)()> void doit() { std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(fn)); } template<class T, void (Small::*fn)(T)> void doit(T x) { std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::bind2nd(std::mem_fun(fn), x)); } public: std::vector<Small *> VectorOfSmalls; }; int main() { Big b; b.VectorOfSmalls.push_back(new Small); b.VectorOfSmalls.push_back(new Small); b.doit<&Small::foo>(); b.doit<int, &Small::bar>(5); }