
Pointers to Functions The C++ Programming Language Pointers to functions are a surprisingly use- ful and frequently underutilized feature of C and C++. Pointers to Memb er Functions Pointers to functions provide an ecient and e ective form of subprogram gener- ality Outline { e.g., the qsort standard C library function: qsort (void *, int, int, int (*)(void *,void *)); static int asc cmp (void *i, void *j) f Pointers to Functions return *(int *)i *(int *)j; g Pointers to Memb er Functions static int dsc cmp (void *i, void *j) f return *(int *)j *(int *)i; The Typ e of a Class Memb er g void print (int a[], int size) f Declaring a Pointer to Memb er Function for (int i = 0; i < size; i++) printf ("%d", a[i]); Pointer to Class Memb er Function putchar('\n'); g Using typ edef to Enhance Readability void main (void) f int a[] = f 9, 1, 7, 4, 5, 8, 3, 1, 2, 0g; Function Arguments int size = sizeof a/ sizeof *a; print (a, size); Using a Pointer to Class Memb er Function cmp); qsort (a, size, sizeof *a, asc print (a, size); Di erence between PTMF and PTF cmp); qsort (a, size, sizeof *a, dsc print (a, size); Pointer to Class Data Memb er g Using a Pointer to Data Memb er 1 2 Pointers to Memb er Functions The Typ e of a Class Memb er Pointers to memb er functions provide an A p ointer to a function cannot b e assigned implementation-i ndep endent way of declar- the address of a memb er function even ing and using p ointers to class memb er when the return typ e and signature of the functions. two match exactly: { Note, this works with virtual and non-virtual class Screen f functions! private: short height, width; char *screen, *cur pos; public: Earlier C++ versions required tricking the Screen (int = 8, int = 40, char = ''); C++ typ e system into utilizi ng the inter- ~Screen (void); nal non-memb er function representation int get height (void) f return height; g to achieve p ointer to memb er function se- int get width (void) f return width; g mantics, e.g., Screen &forward (void); Screen &up (void); Screen &down (void); struct X f void f(int); int i, j; g; Screen &home (void); typ edef void (*PTF) (:::); // Bad style. Screen &b ottom (void); Screen &display(void); void f(void) f Screen &copy (Screen &); PTF fake = (PTF) &X::f; // Assume a lot! // ::: Xa; g; (*fake)(&a, 2); // Fakethecall:: : g int height is (void) f /* :::*/ g int width is (void) f /* :::*/ g This approach is clearly inelegant and error- int (*pt )(void); prone. is; // OK pt = &height pt = &width is; // OK { and do esn't work at all if f is a virtual function! pt = &Screen::get height; // Error pt = &Screen::get width; // Error 3 4 Declaring a Pointer to Memb er Pointer to Class Memb er Function Function A memb er function has an additional typ e attribute absent from a non-memb er func- As mentioned ab ove, a p ointer to memb er tion, namely: \its class." A p ointer to a function is de ned by sp ecifying its return memb er function must match exactly in three areas: typ e, its signature, and its class. { The data typ es and numb er of its formal argu- ments. Therefore, i.e., the function's signature. { A p ointer to the Screen memb er functions are de ned for Screen::get height () and { The function's return data typ e. width () as: Screen::get { The class typ e of which the function is a mem- int (Screen::*)(void); ber. { That is, a p ointer to a memb er function of class Screen taking no arguments and re- turning a value of typ e int, e.g., The declaration of a p ointer to a class int (Screen::*pmf1)(void) = 0; memb er function is similar to a regular height; int (Screen::*pmf2)(void) = &Screen::get p ointer to a function. { However, it also requires an expanded syntax pmf1 = pmf2; that takes the class typ e into account. pmf2 = &Screen::get width; 5 6 Pointers to static Class Memb er Using typ edef to Enhance Functions Readability Note that static class memb er functions behave di erently that non-static mem- Use of a typ edef can make the p ointer to b er functions wrt p ointers-to-memb er func- tions. memb er function syntax easier to read. { i.e., static class memb er functions b ehave like regularnon-memb er functions. For example, the following typ edef de- nes ACTION to be an alternative name { e.g., for: class Foo f Screen &(Screen::*)(void); public: static int si (void); int nsi (void); That is, a p ointer to a memb er function of class Screen taking no arguments and g; returning a reference to a class Screen ob- int (*pts ) (void); ject, e.g., int (Fo o::*ptns ) (void); typ edef Screen &(Screen::*ACTION)(void); pts = &Fo o::si; // ok pts = &Fo o::nsi; // Error ACTION default = &Screen::home; ptns = &Fo o::si; // Error ACTION next = &Screen::forward; ptns = &Fo o::nsi; // ok 7 8 Using a Pointer to Class Memb er Function Function Arguments Pointers to class memb ers must always b e Pointers to memb ers may be declared as accessed through a sp eci c class objects. arguments to functions, in addition, ade- fault initiali z er may also be sp eci ed: This is accomplished by using .* and ->*, typ edef Screen &(Screen::*ACTION)(void); the two p ointer-to-memb er selection op- erators, e.g., screen; Screen my ACTION default = &Screen::home; Screen my screen, *buf screen = &my screen; height; int (Screen::*pm )(void) = &Screen::get Screen &(Screen::*pmfs)(Screen &) = &Screen::copy; Screen& fo o (Screen&, ACTION = &Screen::display); /* :::*/ void (void) f fo o (my screen); // pass &Screen::display // Direct invo cation of memb er functions screen, default); fo o (my if (my screen.get height () == buf screen->get height ()) fo o (my screen, &Screen::b ottom); buf screen->copy(my screen); g // Pointer to memb er equivalent screen.*pm ) () == (buf screen->*pm )()) if ((my (buf screen->*pmfs)(my screen); 9 10 Using a Pointer to Class Memb er Using a Pointer to Class Memb er Function (cont'd) Function (cont'd) A non-general implementation of a rep eat function, that p erforms some user-sp eci ed A declaration wishing to provide default op eration n times could be done the fol- arguments for memb er function repeat () lowing way: might lo ok as follows: enum Op eration f UP,DOWN, /* :::*/ g; class Screen Screen &Screen::rep eat (Op eration op, int times) f f switch (op) public: f Screen &rep eat (ACTION = &Screen::forward, case DOWN: /* co de to iterate n times */; break; int = 1); case UP: /* co de to iterate n times */; /* :::*/ break; g; g return *this; g An invo cation of rep eat might lo ok as fol- lows: Pointers to memb er functions allowamore general implementation: Screen my screen; typ edef Screen &(Screen::*ACTION)(void); /* :::*/ Screen &Screen::rep eat (ACTION op, int times) f for (int i = 0; i < times; i++) my screen.rep eat (); // rep eat (&Screen::forward, 1); (this->*op) (); screen.rep eat (&Screen::down, 20); my return *this; g 12 11 Di erence between PTMF and Example Usage (cont'd) PTF A table of p ointers to class memb ers can also b e de ned. In the following example, e.g., menu is a table of p ointers to class Screen memb er functions that provide for cursor movement: #include <stream.h> class Base 1 f ACTION menu[] = public: f void a1 (int); &Screen::home; static void a2 (int); // Note static::: &Screen::forward; g; &Screen::back; &Screen::up; &Screen::down; // Pointer to function typ e &Screen::b ottom; PTR)(int); typ edef void (*F g; enum Cursor Movements // Pointer to Base 1 memb er function typ e f 1::*MF PTR)(int); typ edef void (Base HOME, FORWARD, BACK, UP,DOWN, BOTTOM g; void a3 (int i); // Forward decl. Movements cm) Screen &Screen::move (Cursor class Base 2 f f public: (this->*menu[cm])(); void b1 (MF PTR); return *this; PTR); void b2 (F g g; 14 13 Di erence between PTMF and Di erence between PTMF and PTF (cont'd) PTF (cont'd) e.g., main program void Base 1::a1 (int i) f cout << "Base 1::a1 got " << i << "\n"; int main (void) f g cout << "base 2.b1 (base 1.a1);\n"; base 2.b1 (base 1.a1); void Base 1::a2 (int i) f // Base 1::a1 got 3 cout << "Base 1::a2 got " << i << "\n"; g 2.b2 (a3);\n"; cout << "\nbase base 2.b2 (a3); void a3 (int i) f cout << "a3 got " << i << "\n"; // a3 got 5 g cout << "\nbase 2.b2 (base 1.a2);\n"; // De ne tw objects. 2.b2 (base 1.a2); base 1base 1; Base // Base 1::a2 got 5 Base 2base 2; cout << "\nbase 2.b2 (Base 1::a2);\n"; 2::b1 (MF PTR fp) f void Base 2.b2 (Base 1::a2); base /* Note object:::*/ (base 1.*fp)(3); 1::a2 got 5 // Base g return 0; 2::b2 (F PTR fp) f (*fp)(5); g void Base g 15 16 Pointer to Class Data Memb er Using a Pointer to Data Memb er In addition to p ointers to memb er func- Pointers to data memb ers are accessed in tions, C++ also allows p ointers to data a manner similar to that use for p ointer memb ers.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages5 Page
-
File Size-