Pointers to Member Functions

Up until this point, all the function pointers you've created have been for general, non-class functions. It is also possible to create pointers to functions that are members of classes.

To create a pointer to member function, use the same syntax as with a pointer to a function, but include the class name and the scoping operator (::). Thus, if pFunc points to a member function of the class Shape, which takes two integers and returns void, the declaration for pFunc is the following:

void (Shape::*pFunc) (int, int);

Pointers to member functions are used in exactly the same way as pointers to functions, except that they require an object of the correct class on which to invoke them. Listing 20.9 illustrates the use of pointers to member functions.

Some compilers do not support the use of a function name as a synonym for its address. If your compiler gives you a warning or error with this listing, try changing lines 71–76 to

71:   case 1:
72:       pFunc = & Mammal::Speak;
73:       break;
74:   default:
75:       pFunc = & Mammal::Move;
76:       break;

and then make the same change on all subsequent listings. (Note addition of ampersand (&) on each line.)


Listing 20.9. Pointers to Member Functions
 0:  //Listing 20.9 Pointers to member functions
 1:  #include <iostream>
 2:
 3:  enum BOOL {FALSE, TRUE};
 4:
 5:  class Mammal
 6:  {
 7:  public:
 8:      Mammal():itsAge(1) {  }
 9:      virtual ~Mammal() { }
10:      virtual void Speak() const = 0;
11:      virtual void Move() const = 0;
12:  protected:
13:      int itsAge;
14:  };
15:
16:  class Dog : public Mammal
17:  {
18:  public:
19:      void Speak()const { std::cout << "Woof!
"; }
20:      void Move() const { std::cout << "Walking to heel...
"; }
21:  };
22:
23:  class Cat : public Mammal
24:  {
25:  public:
26:      void Speak()const { std::cout << "Meow!
"; }
27:      void Move() const { std::cout << "slinking...
"; }
28:  };
29:
30:  class Horse : public Mammal
31:  {
32:  public:
33:      void Speak()const { std::cout << "Winnie!
"; }
34:      void Move() const { std::cout << "Galloping...
"; }
35:  };
36:
37:  int main()
38:  {
39:      void (Mammal::*pFunc)() const =0;
40:      Mammal* ptr =0;
41:      int Animal;
42:      int Method;
43:      bool fQuit = false;
44:
45:      while (fQuit == false)
46:      {
47:          std::cout << "(0)Quit (1)dog (2)cat (3)horse: ";
48:          std::cin >> Animal;
49:          switch (Animal)
50:          {
51:          case 1:
52:              ptr = new Dog;
53:              break;
54:          case 2:
55:              ptr = new Cat;
56:              break;
57:          case 3:
58:              ptr = new Horse;
59:              break;
60:          default:
61:              fQuit = true;
62:              break;
63:          }
64:          if (fQuit)
65:              break;
66:
67:          std::cout << "(1)Speak  (2)Move: ";
68:          std::cin >> Method;
69:          switch (Method)
70:          {
71:          case 1:
72:              pFunc = Mammal::Speak;
73:              break;
74:          default:
75:              pFunc = Mammal::Move;
76:              break;
77:          }
78:
79:          (ptr->*pFunc)();
80:          delete ptr;
81:      }
82:      return 0;
83:  }


 (0)Quit (1)Dog (2)Cat (3)Horse: 1
 (1)Speak (2)Move: 1
Woof!
 (0)Quit (1)Dog (2)Cat (3)Horse: 2
 (1)Speak (2)Move: 1
Meow!
 (0)Quit (1)Dog (2)Cat (3)Horse: 3
 (1)Speak (2)Move: 2
Galloping
 (0)Quit (1)Dog (2)Cat (3)Horse: 0
					

On lines 5–14, the abstract data type Mammal is declared with two pure virtual methods, Speak() and Move(). Mammal is subclassed into Dog, Cat, and Horse, each of which overrides Speak() and Move().


The main() function asks the user to choose which type of animal to create, and then a new subclass of Animal is created on the free store and assigned to ptr on lines 49–63.

The user is then prompted for which method to invoke, and that method is assigned to the pointer pFunc. On line 79, the method chosen is invoked by the object created, by using the pointer ptr to access the object and pFunc to access the function.

Finally, on line 80, delete is called on the pointer ptr to return the memory set aside for the object to the heap. Note that there is no reason to call delete on pFunc because this is a pointer to code, not to an object on the heap. In fact, attempting to do so will generate a compile-time error.

Arrays of Pointers to Member Functions

As with pointers to functions, pointers to member functions can be stored in an array. The array can be initialized with the addresses of various member functions, and those can be invoked by offsets into the array. Listing 20.10 illustrates this technique.

Listing 20.10. Array of Pointers to Member Functions
 0:  //Listing 20.10 Array of pointers to member functions
 1:  #include <iostream>
 2:
 3:  class Dog
 4:  {
 5:  public:
 6:      void Speak()const { std::cout << "Woof!
"; }
 7:      void Move() const { std::cout << "Walking to heel...
"; }
 8:      void Eat() const { std::cout << "Gobbling food...
"; }
 9:      void Growl() const { std::cout << "Grrrrr
"; }
10:      void Whimper() const { std::cout << "Whining noises...
"; }
11:      void RollOver() const { std::cout << "Rolling over...
"; }
12:      void PlayDead() const
13:          { std::cout << "Is this the end of Little Caeser?
"; }
14:  };
15:
16:  typedef void (Dog::*PDF)()const;
17:  int main()
18:  {
19:      const int MaxFuncs = 7;
20:      PDF DogFunctions[MaxFuncs] =
21:          {   Dog::Speak,
22:              Dog::Move,
23:              Dog::Eat,
24:              Dog::Growl,
25:              Dog::Whimper,
26:              Dog::RollOver,
27:              Dog::PlayDead
28:          };
29:
30:      Dog* pDog =0;
31:      int Method;
32:      bool fQuit = false;
33:
34:      while (!fQuit)
35:      {
36:          std::cout << "(0)Quit (1)Speak (2)Move (3)Eat (4)Growl";
37:          std::cout << " (5)Whimper (6)Roll Over (7)Play Dead: ";
38:          std::cin >> Method;
39:          if (Method == 0)
40:          {
41:              fQuit = true;
42:              break;
43:          }
44:          else
45:          {
46:              pDog = new Dog;
47:              (pDog->*DogFunctions[Method-1])();
48:              delete pDog;
49:          }
50:      }
51:      return 0;
52:  }


 (0)Quit (1)Speak (2)Move (3)Eat (4)Growl (5)Whimper (6)Roll Over
(7)Play Dead: 1
Woof!
 (0)Quit (1)Speak (2)Move (3)Eat (4)Growl (5)Whimper (6)Roll Over
(7)Play Dead: 4
Grrrrrr
 (0)Quit (1)Speak (2)Move (3)Eat (4)Growl (5)Whimper (6)Roll Over
(7)Play Dead: 7
Is this the end of Little Caesar?
 (0)Quit (1)Speak (2)Move (3)Eat (4)Growl (5)Whimper (6)Roll Over
(7)Play Dead: 0
						

On lines 3–14, the class Dog is created with seven member functions all sharing the same return type and signature. On line 16, a typedef declares PDF to be a pointer to a member function of Dog that takes no parameters and returns no values, and that is const: the signature of the seven member functions of Dog.

On lines 20–29, the array DogFunctions is declared to hold seven such member functions, and it is initialized with the addresses of these functions.

On lines 36 and 37, the user is prompted to pick a method. Unless he picks Quit, a new Dog is created on the heap, and then the correct method is invoked on the array on line 47. Here's another good line to show to any hotshot C++ programmers you know; ask them what this does:

(pDog->*DogFunctions[Method-1])();

Once again, this is a bit esoteric, but when you need a table built from member functions, it can make your program far easier to read and understand.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.94.153