home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!news.tek.com!psgrain!charnel!rat!usc!cs.utexas.edu!zaphod.mps.ohio-state.edu!uwm.edu!linac!att!att!allegra!alice!bs
- From: bs@alice.att.com (Bjarne Stroustrup)
- Newsgroups: comp.lang.c++
- Subject: Re: Invoking functions passed as parameters
- Message-ID: <24149@alice.att.com>
- Date: 11 Nov 92 02:55:39 GMT
- Article-I.D.: alice.24149
- References: <1992Nov10.192709.682@netcom.com>
- Organization: AT&T Bell Laboratories, Murray Hill NJ
- Lines: 116
-
-
-
- dx@netcom.com (dx @ Netcom - Online Communication Services) writes
-
- > In standard C, function pointers passed as paramters are invoked with
- > the standard C syntax, e.g.,
- >
- > foo(void (*pf)(parmeters))
- > {
- > pf(paremeters)
- > }
- >
- > Now suppose I have a class PFCLASS, and pf points to a member function of
- > this class, and within foo I want to apply the method pointed to by pf to
- > an instance of PFCLASS, pointed to by pInstance.
- >
- > In standard C syntax, I would make the member function take the pointer to
- > the instance as a parameter, and use the standard way to call the function:
- >
- > pf(pInstance);
- >
- > But I wonder if there is some way to invoke the method pointed to by pf
- > in a more C++ like way, such that pInstance turns up as the 'this' pointer
- > in the method, rather than having to pass it as a parameter.
- >
- > Any ideas?
-
- First of all: Naturally, the C style works. You only need to go further
- if there is a real need.
-
- Consider:
-
- class X {
- // ...
- public:
- // ...
- virtual int f1(int);
- virtual int f2(int);
- };
-
-
- Solution #1:
-
- int g1(X* p, int i)
- {
- return p->f1(i);
- }
-
- The C-style function g1() calls f1 for a given object. A pointer to g1()
- can be passed. This is inelegant in some contexts, but have the advantage
- that g1() might be passed to a C program if declared extern "C".
-
- Solution #2:
-
- typedef int (X::* PMF)(int);
-
- PMF is a pointer to member of X type. We can use it like this:
-
- int g2(X* p, PMF f, int i)
- {
- return (p->*f)(i);
- }
-
- g2() calls the member function pointed to by `f' for the object
- pointed to by `p.' For example:
-
- int (X::* f)(int) = &X::f1;
- int (X::* ff)(int) = &X::f2;
- X obj;
-
- void m()
- {
- g2(&obj,f,2); // obj.f1(2)
- g2(&obj,ff,4); // obj.f2(4)
- }
-
- Pointers to members are described in sec5.5 of the reference manual (pg71
- of the ARM , pg502 and 167 of ``The C++ Programming Language (2nd edition)'').
-
- This solves the problem as stated, but just for fun let's explore this a bit:
-
- Solution #3:
-
- class XFunc {
- PFM f;
- X* p;
- public:
- XFunc(PMF ff, X* pp) { f=ff; p=pp; }
- int operator()(int i) { return (p->*f)(i); }
- };
-
- That is, an object of class `XFunc' contains the information needed to
- call a member function for an object and can be called:
-
- XFunc xf(&X::f1,&obj);
- XFunc xff(&X::f2,&obj);
-
- xf(2); // obj.f1(2)
- xff(4); // obj.f2(4)
-
- Note that objects of type `func' can be passed around easily and safely:
-
- int xcall(XFunc& x, int i)
- {
- x(i); // call whatever member function x holds
- // for whatever object x holds a pointer to
- }
-
- void m1()
- {
- xcall(xf,2); // obj.f1(2)
- xcall(xff,4); // obj.f1(4)
- }
-
- Such ``functional objects'' can be very useful, but as usual one
- should only use a technique if there is a real need.
-