The C++ Programming Language Pointers to Member Functions

The C++ Programming Language Pointers to Member Functions

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.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    5 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us