It's best to have a nodding acquaintance with pointers to members before talking about these more useful cousins of theirs.
A C++ class (or struct) has more than just data members: it has member functions (or methods). Just as a regular pointer to member abstracts the concept of a data member of given type of some class, a pointer to a member function abstracts the concept of a member function of given type of some class.
Once you've stomached the atrocities of both C's function pointers and C++'s pointer to member, the syntax for declaring a pointer to a member function should be completely natural. However, once it appears "completely natural", commission by main force to a lunatic asylum is advised... For instance, if we have
class X {
int a;
public:
X(int a_) : a(a_) {}
int add(int b) { return a+b; }
int mul(int b) { return a*b; }
int mod(int b) { return a%b; }
void print() { std::cout << a << endl; }
};
X x(2), y(17);
vector<X> vx;
then by saying "int (X::*pxf)(int)" we may declare pxf as a pointer to any member function of X which takes and returns an int. In particular, we may write "pxf = &X::mul;" to make pxf refer to the member function mul of X. We cannot, however, say "pxf = &X::print;" -- pxf has the wrong type. (Note that X::print, however, has
no type! This is another example of the phenomenon seen in the
freakshow entry
C++: objects with no type).
The use of pointers to member functions to create some callbacks is discussed in the node ->*.
Another use appears in the standard library. The STL supplies a template function for_each, which performs a function object or functor on each element of a range. Unfortunately, for_each requires a function object -- so we cannot directly use it to print each element of vx above. We could write an adaptor function for X::print above, and use that with for_each:
void printX(X* px) { px->print(); }
But that's error-prone, and -- if used a lot -- even uglier than pointers to member functions!
So the STL provides mem_fun, which converts a void method of no parameters into a function object. Stripped of details extraneous to this discussion, it looks like this:
template<typename T, typename R>
class mem_fun {
R (T::*f); // member function to call
public:
mem_fun(T::*f_) : f(f_) {};
R operator()(T& me) { return me.*f(); }
};
All a mem_fun<X,void> does is convert function object calls of the form "
function(rx)" (where X& rx is a
reference to an X) into member function calls of the form "rx.
function()". We can say "for_each(v
.begin(), v
.end(), mem_fun(&X::print))" to print each member of v.
The STL also provides similar adaptors for functions taking additional arguments. And, as the core language supports the needed syntax, you can write additional adaptors as needed.
Of course everything works with inheritance. You can take pointers to virtual member functions, apply them to pointers to the base class, and everything just works. IF, of course, these virtual member functions were defined in the base. If the member functions were added in the derived class, then -- virtual or not -- you have a type error: A pointer to a member function of the base cannot hold something which is not a member function of the base.
YUCK.