Function Pointers

A pointer to a function contains the address of the function in memory. In Chapter 7, we saw that the name of an array is actually the address in memory of the first element of the array. Similarly, the name of a function is actually the starting address in memory of the code that performs the function's task. Pointers to functions can be passed to functions, returned from functions, stored in arrays and assigned to other function pointers.

Multipurpose Selection Sort Using Function Pointers

To illustrate the use of pointers to functions, Fig. 8.28 modifies the selection sort program of Fig. 8.15. Figure 8.28 consists of main (lines 1755) and the functions selectionSort (lines 5976), swap (lines 8085), ascending (lines 8992) and descending (lines 9699). Function selectionSort receives a pointer to a functioneither function ascending or function descendingas an argument in addition to the integer array to sort and the size of the array. Functions ascending and descending determine the sorting order. The program prompts the user to choose whether the array should be sorted in ascending order or in descending order (lines 2426). If the user enters 1, a pointer to function ascending is passed to function selectionSort (line 37), causing the array to be sorted into increasing order. If the user enters 2, a pointer to function descending is passed to function selectionSort (line 45), causing the array to be sorted into decreasing order.

Figure 8.28. Multipurpose sorting program using function pointers.

(This item is displayed on pages 439 - 441 in the print version)

 1 // Fig. 8.28: fig08_28.cpp
 2 // Multipurpose sorting program using function pointers.
 3 #include 
 4 using std::cout;
 5 using std::cin;
 6 using std::endl;
 7
 8 #include 
 9 using std::setw;
10
11 // prototypes
12 void selectionSort( int [], const int, bool (*)( int, int ) );
13 void swap( int * const, int * const );
14 bool ascending( int, int ); // implements ascending order
15 bool descending( int, int ); // implements descending order
16
17 int main()
18 {
19 const int arraySize = 10;
20 int order; // 1 = ascending, 2 = descending
21 int counter; // array index
22 int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
23
24 cout << "Enter 1 to sort in ascending order,
"
25 << "Enter 2 to sort in descending order: ";
26 cin >> order;
27 cout << "
Data items in original order
";
28
29 // output original array
30 for ( counter = 0; counter < arraySize; counter++ )
31 cout << setw( 4 ) << a[ counter ];
32
33 // sort array in ascending order; pass function ascending
34 // as an argument to specify ascending sorting order
35 if ( order == 1 )
36 {
37 selectionSort( a, arraySize, ascending );
38 cout << "
Data items in ascending order
";
39 } // end if
40
41 // sort array in descending order; pass function descending
42 // as an argument to specify descending sorting order
43 else
44 {
45 selectionSort( a, arraySize, descending );
46 cout << "
Data items in descending order
";
47 } // end else part of if...else
48
49 // output sorted array
50 for ( counter = 0; counter < arraySize; counter++ )
51 cout << setw( 4 ) << a[ counter ];
52
53 cout << endl;
54 return 0; // indicates successful termination
55 } // end main
56
57 // multipurpose selection sort; the parameter compare is a pointer to
58 // the comparison function that determines the sorting order
59 void selectionSort( int work[], const int size,
60 bool (*compare)( int, int ) )
61 {
62 int smallestOrLargest; // index of smallest (or largest) element
63
64 // loop over size - 1 elements
65 for ( int i = 0; i < size - 1; i++ )
66 {
67 smallestOrLargest = i; // first index of remaining vector
68
69 // loop to find index of smallest (or largest) element
70 for ( int index = i + 1; index < size; index++ )
71 if ( !(*compare)( work[ smallestOrLargest ], work[ index ] ) )
72 smallestOrLargest = index;
73
74 swap( &work[ smallestOrLargest ], &work[ i ] );
75 } // end if
76 } // end function selectionSort
77
78 // swap values at memory locations to which
79 // element1Ptr and element2Ptr point
80 void swap( int * const element1Ptr, int * const element2Ptr )
81 {
82 int hold = *element1Ptr;
83 *element1Ptr = *element2Ptr;
84 *element2Ptr = hold;
85 } // end function swap
86
87 // determine whether element a is less than 
88 // element b for an ascending order sort 
89 bool ascending( int a, int b ) 
90 { 
91  return a < b; // returns true if a is less than b
92 } // end function ascending 
93
94 // determine whether element a is greater than 
95 // element b for a descending order sort 
96 bool descending( int a, int b ) 
97 { 
98  return a > b; // returns true if a is greater than b
99 } // end function descending 
 
 Enter 1 to sort in ascending order,
 Enter 2 to sort in descending order: 1

 Data items in original order
 2 6 4 8 10 12 89 68 45 37
 Data items in ascending order
 2 4 6 8 10 12 37 45 68 89
 
 
 Enter 1 to sort in ascending order,
 Enter 2 to sort in descending order: 2

 Data items in original order
 2 6 4 8 10 12 89 68 45 37
 Data items in descending order
 89 68 45 37 12 10 8 6 4 2
 

The following parameter appears in line 60 of selectionSort's function header:

bool ( *compare )( int, int )

This parameter specifies a pointer to a function. The keyword bool indicates that the function being pointed to returns a bool value. The text ( *compare ) indicates the name of the pointer to the function (the * indicates that parameter compare is a pointer). The text ( int, int ) indicates that the function pointed to by compare takes two integer arguments. Parentheses are needed around *compare to indicate that compare is a pointer to a function. If we had not included the parentheses, the declaration would have been

bool *compare( int, int )

which declares a function that receives two integers as parameters and returns a pointer to a bool value.


The corresponding parameter in the function prototype of selectionSort is

bool (*)( int, int )

Note that only types have been included. As always, for documentation purposes, the programmer can include names that the compiler will ignore.

The function passed to selectionSort is called in line 71 as follows:

( *compare )( work[ smallestOrLargest ], work[ index ] )

Just as a pointer to a variable is dereferenced to access the value of the variable, a pointer to a function is dereferenced to execute the function. The parentheses around *compare are again necessaryif they were left out, the * operator would attempt to dereference the value returned from the function call. The call to the function could have been made without dereferencing the pointer, as in

compare( work[ smallestOrLargest ], work[ index ] )

which uses the pointer directly as the function name. We prefer the first method of calling a function through a pointer, because it explicitly illustrates that compare is a pointer to a function that is dereferenced to call the function. The second method of calling a function through a pointer makes it appear as though compare is the name of an actual function in the program. This may be confusing to a user of the program who would like to see the definition of function compare and finds that it is not defined in the file.


Arrays of Pointers to Functions

One use of function pointers is in menu-driven systems. For example, a program might prompt a user to select an option from a menu by entering an integer values. The user's choice can be used as a subscript into an array of function pointers, and the pointer in the array can be used to call the function.

Figure 8.29 provides a mechanical example that demonstrates declaring and using an array of pointers to functions. The program defines three functionsfunction0, function1 and function2that each take an integer argument and do not return a value. Line 17 stores pointers to these three functions in array f. In this case, all the functions to which the array points must have the same return type and same parameter types. The declaration in line 17 is read beginning in the leftmost set of parentheses as, "f is an array of three pointers to functions that each take an int as an argument and return void." The array is initialized with the names of the three functions (which, again, are pointers). The program prompts the user to enter a number between 0 and 2, or 3 to terminate. When the user enters a value between 0 and 2, the value is used as the subscript into the array of pointers to functions. Line 29 invokes one of the functions in array f. In the call, f[ choice ] selects the pointer at location choice in the array. The pointer is dereferenced to call the function, and choice is passed as the argument to the function. Each function prints its argument's value and its function name to indicate that the function is called correctly. In the exercises, you will develop a menu-driven system. We will see in Chapter 13, Object-Oriented Programming: Polymorphism, that arrays of pointers to functions are used by compiler developers to implement the mechanisms that support virtual functionsthe key technology behind polymorphism.


Figure 8.29. Array of pointers to functions.

(This item is displayed on pages 442 - 443 in the print version)

 1 // Fig. 8.29: fig08_29.cpp
 2 // Demonstrating an array of pointers to functions.
 3 #include 
 4 using std::cout;
 5 using std::cin;
 6 using std::endl;
 7
 8 // function prototypes -- each function performs similar actions
 9 void function0( int );
10 void function1( int );
11 void function2( int );
12
13 int main()
14 {
15 // initialize array of 3 pointers to functions that each 
16 // take an int argument and return void 
17 void (*f[ 3 ])( int ) = { function0, function1, function2 };
18
19 int choice;
20
21 cout << "Enter a number between 0 and 2, 3 to end: ";
22 cin >> choice;
23
24 // process user's choice
25 while ( ( choice >= 0 ) && ( choice < 3 ) )
26 {
27 // invoke the function at location choice in 
28 // the array f and pass choice as an argument
29 (*f[ choice ])( choice ); 
30
31 cout << "Enter a number between 0 and 2, 3 to end: ";
32 cin >> choice;
33 } // end while
34
35 cout << "Program execution completed." << endl;
36 return 0; // indicates successful termination
37 } // end main
38
39 void function0( int a )
40 {
41 cout << "You entered " << a << " so function0 was called

";
42 } // end function function0
43
44 void function1( int b )
45 {
46 cout << "You entered " << b << " so function1 was called

";
47 } // end function function1
48
49 void function2( int c )
50 {
51 cout << "You entered " << c << " so function2 was called

";
52 } // end function function2
 
 Enter a number between 0 and 2, 3 to end: 0
 You entered 0 so function0 was called

 Enter a number between 0 and 2, 3 to end: 1
 You entered 1 so function1 was called

 Enter a number between 0 and 2, 3 to end: 2
 You entered 2 so function2 was called

 Enter a number between 0 and 2, 3 to end: 3
 Program execution completed.
 




C++ How to Program
C++ How to Program (5th Edition)
ISBN: 0131857576
EAN: 2147483647
Year: 2004
Pages: 627
Simiral book on Amazon

Flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net