Function Pointers

 < Day Day Up > 



Function pointers are cool! Just like you can declare a pointer to an object, so too can you declare a pointer to a function. The address of an existing function can then be assigned to and called via the function pointer. There are many great uses for function pointers, as you will see shortly. Also, an understanding of function pointers will help you understand the C++ virtual function call mechanism which is implemented as an array of function pointers. Let us start by looking at how function pointers are declared.

Declaring Function Pointers

The function pointer syntax looks a little strange at first glance but it is easy to master. The following code declares a pointer named fun_ptr to a function that returns a float and takes two float arguments:

float (*fun_ptr)(float, float);

This next example declares a function pointer named sortDirection that can point to a function that returns a bool and takes two integer arguments:

bool (*sortDirection)(int, int);

Now that you have a pointer to a type of function, all you need now is a function to point to!

Assigning The Address of a Function to a Function Pointer

Here is a function declaration for a function named add() that returns a float and takes two float arguments:

float add(float a, float b);

Here is the definition for this function:

float add(float a, float b){return a+b;}

Now armed with a function pointer and a function to point to, here is how you assign the function’s address to the function pointer:

fun_ptr = add;

Calling the Function via the Function Pointer

After assigning the address of a function to a function pointer you can now call the function via the pointer. The following code gives an example:

cout<<fun_ptr(5,5)<<endl;

When this line of code executes, the value 10 will be printed to the screen.

Arrays of Function Pointers

You can create interesting behavior by building an array of function pointers and assigning different functions to each pointer. The following complete example illustrates how to create an array of function pointers, assign a different function to each array element, and then iterate over the array calling each function via the function pointer. Let us start with the header file that declares four arithmetic functions add(), sub(), mul(), and div():

Listing 9.49: arithfunctions.h

start example
 1  #ifndef ARITH_FUNCTIONS_H  2  #define ARITH_FUNCTIONS_H  3  4  float add(float a, float b);  5  float sub(float a, float b);  6  float mul(float a, float b);  7  float div(float a, float b);  8  9  #endif
end example

The following listing gives the definition for each of these functions:

Listing 9.50: arithfunctions.cpp

start example
 1  #include "arithfunctions.h"  2  3  float add(float a, float b){return a+b;}  4  float sub(float a, float b){return a-b;}  5  float mul(float a, float b){return a*b;}  6  float div(float a, float b){return a/b;}
end example

The following main() creates the array of function pointers and assigns each of these arithmetic functions to an array element:

Listing 9.51: main.cpp

start example
 1  #include <iostream>  2  #include "arithfunctions.h"  3  using namespace std;   4  5  int main(){  6      typedef float (*fun_ptr)(float, float);  7  8      fun_ptr fun_ptr_array[4];  9 10      fun_ptr_array[0] = add; 11      fun_ptr_array[1] = sub; 12      fun_ptr_array[2] = mul; 13      fun_ptr_array[3] = div; 14 15      for(int i = 0; i < 4; i++) 16          cout<<fun_ptr_array[i](5,5)<<endl; 17      return 0; 18  }
end example

Line 6 uses the typedef keyword to create a function pointer type synonym named fun_ptr. The synonym is then used on line 8 to create an array of function pointers named fun_ptr_array. Note that each array element can only point to a function of fun_ptr type. In other words, each element can only point to functions that return a float and take two float arguments.

On lines 10 through 13 the addresses of the functions add(), sub(), mul(), and div() are assigned to each array element. The for loop on line 15 then iterates over fun_ptr_array and calls each function via its pointer with two arguments.

Let us now take a look at another interesting use for function pointers — callback functions.

Implementing Callback Functions with Function Pointers

It is often desirable to change the behavior of a function by calling the function with a behavior-modifying function as one of its arguments. The behavior-modifying function is referred to as a callback function. The following complete example will revisit a simple sort routine encountered in chapter 4 called dumbsort. By rewriting the dumbsort function to take a callback function, dumbsort’s behavior can be modified so it can sort in ascending or descending order based on what callback function is supplied as an argument when the dumbsort function is called. The following code gives the function declaration for dumbSort() and two utility functions named compareAscending() and compareDescending):

Listing 9.52: dumbsort.h

start example
 1  #ifndef DUMB_SORT_H  2  #define DUMB_SORT_H  3  4  void dumbSort(int a[], int l, int r, bool (*sortDirection) (int, int));  5  bool compareAscending(int a, int b);  6  bool compareDescending(int a, int b);  7  8  #endif
end example

Notice how the declaration for dumbSort() includes a function pointer parameter named sortDirection. The sortDirection parameter will take a pointer to either the compareAscending() function or the compareDescending() function as an argument. The sortDirection function pointer is then used in the body of the dumbSort() function to provide the comparison of two array elements. The following code gives the definitions for all three functions declared above:

Listing 9.53: dumbsort.cpp

start example
 1  #include "dumbsort.h"  2  3  bool compareAscending(int a, int b){return a>b;}  4  bool compareDescending(int a, int b){return a<b;}  5  6  void dumbSort(int a[], int l, int r, bool (*sortDirection) (int, int)){  7     for(int i = l; i< r; i++){  8       for(int j = (l+1); j < r; j++){  9        if(sortDirection(a[j-1], a[j])) { 10          int temp = a[j-1]; 11          a[j-1] = a[j]; 12          a[j] = temp; 13        } 14       } 15     } 16  }
end example

The compareAscending() and compareDescending() functions each return the boolean value that results from comparing two integer arguments via the > or < operators. The dumbSort() function takes the sortDirection function pointer parameter and calls the supplied function argument in the expression test of the if statement on line 9. By using the appropriate callback function, dumbSort()’s sorting behavior can be changed to sort in either ascending or descending order. The following main() function shows dumbSort() and the callback function mechanism in action.

Listing 9.54: main.cpp

start example
 1  #include <iostream>  2  #include "dumbsort.h"  3  using namespace std;   4  5  int main(){  6  7     int int_array[10] = {34,3,16,2,8,10,1,0,5,11};  8  9     for(int i = 0; i<10; i++) 10        cout<<int_array[i]<<" "; 11     cout<<endl; 12 13     dumbSort(int_array, 0, 10, compareAscending); 14 15     for(int i = 0; i<10; i++) 16        cout<<int_array[i]<<" "; 17     cout<<endl; 18 19     dumbSort(int_array, 0, 10, compareDescending); 20 21     for(int i = 0; i<10; i++) 22        cout<<int_array[i]<<" "; 23     cout<<endl; 24     return 0; 25  }
end example

On line 7 an array of 10 integers is declared and initialized. It is printed to the screen on lines 9 and 10. On line 13 dumbSort() is called to sort the array in ascending order with the compareAscending() callback function as an argument. The array is then printed to the screen once again and on line 19 dumbSort() is called to again sort the array but this time in descending order using the callback function compareDescending(). Figure 9-16 shows the results of running this program.

click to expand
Figure 9-16: Results of Calling DumbSort() Using compareAscending() and compareDescending() CallBack Functions



 < Day Day Up > 



C++ for Artists. The Art, Philosophy, and Science of Object-Oriented Programming
C++ For Artists: The Art, Philosophy, And Science Of Object-Oriented Programming
ISBN: 1932504028
EAN: 2147483647
Year: 2003
Pages: 340
Authors: Rick Miller

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