[comp.lang.c++] What good are method pointers?

laleak01@ulkyvx.bitnet (06/30/91)

What can you do with pointers to methods?

Why does this fail?:

class Ack {
  public:
  void Func (void) { printf ("Ack.  Thppft.\n"); }
  };

void main (void)
  {
  Ack ack;
  void (Ack::*p) (void);

  p=Ack::Func; // no prob here
  ack.Func(); // string is output
#if 0
  p(); // this complains: "too few parms; need 'this'"
#else
  p(ack); // so I gave it a this.
#endif
  }

p(ack) produces NO output.  I would at least expect it to print "Ack..."

What can you really do with pointers to methods?

-- Arlie Davis, borrowing Linda's account.  (Do not email address.)

steve@taumet.com (Stephen Clamage) (06/30/91)

laleak01@ulkyvx.bitnet, Arlie Davis, borrowing Linda's account, writes:

>class Ack {
>  public:
>  void Func (void) { printf ("Ack.  Thppft.\n"); }
>  };

>void main (void)
>  {
>  Ack ack;
>  void (Ack::*p) (void);
>  p=Ack::Func; // no prob here
>  ack.Func(); // string is output
>  p(); // this complains: "too few parms; need 'this'"
>  p(ack); // so I gave it a this. -- no output
>  }

You almost have it.  A pointer-to-member must be used in conjunction
with some object, because the member to which it points may be accessed
only with reference to some object.  (Except static members, which may
use either pointer-to-member or ordinary pointer, since they stand
alone.)

Your compiler should have complained about p(ack), since that is an
illegal call, as is p(), which it did complain about.

The correct usage is "ack.*p();".  Note the ".*", which is a single
token indicating a dereference of a pointer-to-member.  If we define
	Ack *ackp = &ack;
we can also call Func like this
	ackp->*Func();
The "->*" is also a single token, indicating dereference of a pointer-to-
member accessed from a pointer-to-object.

Pointers-to-member-functions have the desirable feature that they can
point to virtual functions and call the correct virtual function for
a given object.  For example:
	class base { public: virtual foo(); } b;
	class der : public base { public: foo(); } d;
	base *p = &d;	// base* really points to a der
	int (base::*bpf)() = base::foo;	// points to virtual base::foo
	p->*bpf();	// calls der::foo, the correct virtual function
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com