(C++ (and I seriously hope nothing else):)
A pointer to a member of a class is what gives rise to probably the ugliest C++ syntax (so we're talking big-time ugly here): the .* and ->* "operators". A plain pointer abstracts the notion of an lvalue of known type which is not fixed at compile time. The typical implementation of a pointer is as an address. A pointer to a member abstracts the notion of a part of a class (or struct) of known type which is not fixed at compile time. The typical implementation of a pointer to member is as an offset. C++'s pointers to members offer almost all of the uses available with C's offsetof operator, while keeping code type safe.


Suppose we have
struct X {
  int   a;
  float b;
  int   c;
  int   d;
X x, y;
X* p;
vector<X> v;
We can declare (and define) a pointer to an int member of X by saying
int X::* pxi;
pxi can now be used to point to any of the int members of X. For instance, we may say "pxi = &X::c;" to get a pointer to the member c of X. pxi still doesn't point anywhere -- every X has its own c, and pxi points at "c". It is meaningless to dereference a pointer to a member; we can only dereference the combination of a pointer to the class and a pointer to a member. For instance, x.*pxi references x.c, y.*pxi references y.c, p->*pxi references p->c, and v[0].*pxi is v[0].c. But by changing pxi, we can change what the code references: pxi = &X::a; or pxi = &X::d will both work.

Just like pointers, pointers to members have types. For instance, pxi above is a pointer to an int member; saying "pxi = &X::b;" would be an error.

We can use pointers to members to write functions that operate on unknown parts of X. For instance, to convert a vector<X> to the vector of just the int values stored in a particular field (i.e., to convert v to v[0].FIELD, v[1].FIELD, v[2].FIELD, ...), where which int FIELD to use will be specified at run-time, we can write

vector<int> vX_to_vint(vector<X> v, int X::* pxi)
  vector<int> ret;
  for(vector<X>::iterator vi = v.begin(); vi != v.end(); ++vi)
  return ret;
We can use vX_to_vint(v, &X::a) to get the list of all a's in the vector v of X's, or vX_to_vint(v, &X::d) to do the same with the d's. We can even compute which pointer to member we want to pass at run time.

Pointers to members are rarely useful. Their syntax is atrociously ugly, and they are a difficult concept to explain. Pointers to member functions are more often used.

Log in or register to write something here or to contact authors.