C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 33:
[33.13] What the heck is a functionoid, and why would I use one?

Functionoids are functions on steroids. Functionoids are strictly more powerful than functions, and that extra power solves some (not all) of the challenges typically faced when you use function-pointers.

Let's work an example showing a traditional use of function-pointers, then we'll translate that example into functionoids. The traditional function-pointer idea is to have a bunch of compatible functions:

int funct1(...params...) { ...code... }
int funct2(...params...) { ...code... }
int funct3(...params...) { ...code... }
Then you access those by function-pointers:
typedef int(*FunctPtr)(...params...);

void myCode(FunctPtr f)
{
  ...
  f(...args-go-here...);
  ...
}
Sometimes people create an array of these function-pointers:
FunctPtr array[10];
array[0] = funct1;
array[1] = funct1;
array[2] = funct3;
array[3] = funct2;
...
In which case they call the function by accessing the array:
array[i](...args-go-here...);
With functionoids, you first create a base class with a pure-virtual method:
class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() = 0;
};

inline Funct::~Funct() { }  // defined even though it's pure virtual; it's faster this way; trust me
Then instead of three functions, you create three derived classes:
class Funct1 : public Funct {
public:
  virtual int doit(int x) { ...code from funct1... }
};

class Funct2 : public Funct {
public:
  virtual int doit(int x) { ...code from funct2... }
};

class Funct3 : public Funct {
public:
  virtual int doit(int x) { ...code from funct3... }
};
Then instead of passing a function-pointer, you pass a Funct*. I'll create a typedef called FunctPtr merely to make the rest of the code similar to the old-fashioned approach:
typedef Funct* FunctPtr;

void myCode(FunctPtr f)
{
  ...
  f->doit(...args-go-here...);
  ...
}
You can create an array of them in almost the same way:
FunctPtr array[10];
array[0] = new Funct1(...ctor-args...);
array[1] = new Funct1(...ctor-args...);
array[2] = new Funct3(...ctor-args...);
array[3] = new Funct2(...ctor-args...);
...
This gives us the first hint about where functionoids are strictly more powerful than function-pointers: the fact that the functionoid approach has arguments you can pass to the ctors (shown above as ...ctor-args...) whereas the function-pointers version does not. Think of a functionoid object as a freeze-dried function-call (emphasis on the word call). Unlike a pointer to a function, a functionoid is (conceptually) a pointer to a partially called function. Imagine for the moment a technology that lets you pass some-but-not-all arguments to a function, then lets you freeze-dry that (partially completed) call. Pretend that technology gives you back some sort of magic pointer to that freeze-dried partially-completed function-call. Then later you pass the remaining args using that pointer, and the system magically takes your original args (that were freeze-dried), combines them with any local variables that the function calculated prior to being freeze-dried, combines all that with the newly passed args, and continues the function's execution where it left off when it was freeze-dried. That might sound like science fiction, but it's conceptually what functionoids let you do. Plus they let you repeatedly "complete" that freeze-dried function-call with various different "remaining parameters," as often as you like. Plus they allow (not require) you to change the freeze-dried state when it gets called, meaning functionoids can remember information from one call to the next.

Okay, let's get our feet back on the ground and we'll work a couple of examples to explain what all that mumbo jumbo really means.

Suppose the original functions (in the old-fashioned function-pointer style) took slightly different parameters.

int funct1(int x, float y)
{ ...code... }

int funct2(int x, std::string const& y, int z)
{ ...code... }

int funct3(int x, const std::vector<double>& y)
{ ...code... }
When the parameters are different, the old-fashioned function-pointers approach is difficult to use, since the caller doesn't know which parameters to pass (the caller merely has a pointer to the function, not the function's name or, when the parameters are different, the number and types of its parameters) (do not write me an email about this; yes you can do it, but you have to stand on your head and do messy things; but do not write me about it — use functionoids instead).

With functionoids, the situation is, at least sometimes, much better. Since a functionoid can be thought of as a freeze-dried function call, just take the un-common args, such as the ones I've called y and/or z, and make them args to the corresponding ctors. You may also pass the common args (in this case the int called x) to the ctor, but you don't have to — you have the option of passing it/them to the pure virtual doit() method instead. I'll assume you want to pass x into doit() and y and/or z into the ctors:

class Funct {
public:
  virtual int doit(int x) = 0;
};
Then instead of three functions, you create three derived classes:
class Funct1 : public Funct {
public:
  Funct1(float y) : y_(y) { }
  virtual int doit(int x) { ...code from funct1... }
private:
  float y_;
};

class Funct2 : public Funct {
public:
  Funct2(std::string const& y, int z) : y_(y), z_(z) { }
  virtual int doit(int x) { ...code from funct2... }
private:
  std::string y_;
  int z_;
};

class Funct3 : public Funct {
public:
  Funct3(const std::vector<double>& y) : y_(y) { }
  virtual int doit(int x) { ...code from funct3... }
private:
  std::vector<double> y_;
};
Now you see that the ctor's parameters get freeze-dried into the functionoid when you create the array of functionoids:
FunctPtr array[10];

array[0] = new Funct1(3.14f);

array[1] = new Funct1(2.18f);

std::vector<double> bottlesOfBeerOnTheWall;
bottlesOfBeerOnTheWall.push_back(100);
bottlesOfBeerOnTheWall.push_back(99);
...
bottlesOfBeerOnTheWall.push_back(1);
array[2] = new Funct3(bottlesOfBeerOnTheWall);

array[3] = new Funct2("my string", 42);

...
So when the user invokes the doit() on one of these functionoids, he supplies the "remaining" args, and the call conceptually combines the original args passed to the ctor with those passed into the doit() method:
array[i]->doit(12);
As I've already hinted, one of the benefits of functionoids is that you can have several instances of, say, Funct1 in your array, and those instances can have different parameters freeze-dried into them. For example, array[0] and array[1] are both of type Funct1, but the behavior of array[0]->doit(12) will be different from the behavior of array[1]->doit(12) since the behavior will depend on both the 12 that was passed to doit() and the args passed to the ctors.

Another benefit of functionoids is apparent if we change the example from an array of functionoids to a local functionoid. To set the stage, let's go back to the old-fashioned function-pointer approach, and imagine that you're trying to pass a comparison-function to a sort() or binarySearch() routine. The sort() or binarySearch() routine is called childRoutine() and the comparison function-pointer type is called FunctPtr:

void childRoutine(FunctPtr f)
{
  ...
  f(...args...);
  ...
}
Then different callers would pass different function-pointers depending on what they thought was best:
void myCaller()
{
  ...
  childRoutine(funct1);
  ...
}

void yourCaller()
{
  ...
  childRoutine(funct3);
  ...
}
We can easily translate this example into one using functionoids:
void childRoutine(Funct& f)
{
  ...
  f.doit(...args...);
  ...
}

void myCaller()
{
  ...
  Funct1 funct(...ctor-args...);
  childRoutine(funct);
  ...
}

void yourCaller()
{
  ...
  Funct3 funct(...ctor-args...);
  childRoutine(funct);
  ...
}
Given this example as a backdrop, we can see two benefits of functionoids over function-pointers. The "ctor args" benefit described above, plus the fact that functionoids can maintain state between calls in a thread-safe manner. With plain function-pointers, people normally maintain state between calls via static data. However static data is not intrinsically thread-safe — static data is shared between all threads. The functionoid approach provides you with something that is intrinsically thread-safe since the code ends up with thread-local data. The implementation is trivial: change the old-fashioned static datum to an instance data member inside the functionoid's this object, and poof, the data is not only thread-local, but it is even safe with recursive calls: each call to yourCaller() will have its own distinct Funct3 object with its own distinct instance data.

Note that we've gained something without losing anything. If you want thread-global data, functionoids can give you that too: just change it from an instance data member inside the functionoid's this object to a static data member within the functionoid's class, or even to a local-scope static data. You'd be no better off than with function-pointers, but you wouldn't be worse off either.

The functionoid approach gives you a third option which is not available with the old-fashioned approach: the functionoid lets callers decide whether they want thread-local or thread-global data. They'd be responsible to use locks in cases where they wanted thread-global data, but at least they'd have the choice. It's easy:

void callerWithThreadLocalData()
{
  ...
  Funct1 funct(...ctor-args...);
  childRoutine(funct);
  ...
}

void callerWithThreadGlobalData()
{
  ...
  static Funct1 funct(...ctor-args...);   the static is the only difference
  childRoutine(funct);
  ...
}
Functionoids don't solve every problem encountered when making flexible software, but they are strictly more powerful than function-pointers and they are worth at least evaluating. In fact you can easily prove that functionoids don't lose any power over function-pointers, since you can imagine that the old-fashioned approach of function-pointers is equivalent to having a global(!) functionoid object. Since you can always make a global functionoid object, you haven't lost any ground. QED.