Pointers to Functions

  1. A pointer may also point at functions or code.

  2. Suppose we wished to produce a table of different functions on a series of numbers like:
    Table of Squares
    1       1
    3       9
    5       25
    7       49
    9       81
    
    Table of Square Roots
    1       1
    3       1.73205
    5       2.23607
    7       2.64575
    9       3
    


  3. Our first program might look like :
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    int main()
    {
      int   a,b,c;
    	 
      cout << "Table of Squares" << endl;
      for(a=1;a<10;a+=2) {
         float square;
         square=a*a;
         cout << a << "\t" << square << endl;
       }
       cout << endl;
       cout << "Table of Square Roots" << endl;
       for(a=1;a<10;a+=2) {
          float sqroot;
          sqroot=(sqrt((float) a));
          cout << a << "\t" << sqroot << endl;
       }
       system("pause");
       return 0;
    }
    

  4. We might want to clean up the code making table an abstraction like:
    //
    //  Pointers to functions
    //
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    void table(string,int,int,int,int);
    float square(int);
    float sqroot(int);
    
    int main()
    {
       table("Squares",1,10,2,1);
       table("Square Roots",2,15,3,2);
       system("pause");
       return 0;
    }
    
    void table(string text, int start, int end, int increment, int function)
    {
    //
    // pre - none
    // post - table of a math function
    //         text for heading
    //         start, end, increment for series
    //         function 1- square, 2 - square root
       int   index;
       float value;
       cout << endl << "Table of " << text << endl;
       for(index=start; index < end ; index+=increment) {
          switch (function) {
             case 1 : value=square(index); break;
             case 2 : value=sqroot(index); break;
             default: value=0;
          }
          cout << index << "\t" << value << endl;
       }
    }
    float square(int x)
    {
       return (float)(x * x);
    }
    float sqroot(int x)
    {
       return sqrt((float) x);
    }
    

  5. Giving the following output:
    
    Table of Squares
    1       1
    3       9
    5       25
    7       49
    9       81
    
    Table of Square Roots
    2       1.41421
    5       2.23607
    8       2.82843
    11      3.31662
    14      3.74166
    

  6. To add another function like cube to the first implementation is just more coding. To add it to our second example we need to add the function cube, alter the table function and call it like:
    //
    //  Pointers to functions
    //
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    void table(string,int,int,int,int);
    float square(int);
    float sqroot(int);
    float cube(int);
    
    int main()
    {
       table("Squares",1,10,2,1);
       table("Square Roots",2,15,3,2);
       table("Cubes",3,12,3,3);
       system("pause");
       return 0;
    }
    
    void table(string text, int start, int end, int increment, int function)
    {
    //
    // pre - none
    // post - table of a math function
    //         text for heading
    //         start, end, increment for series
    //         function 1- square, 2 - square root, 3 - cubes
       int   index;
       float value;
       cout << endl << "Table of " << text << endl;
       for(index=start; index < end ; index+=increment) {
          switch (function) {
             case 1 : value=square(index); break;
             case 2 : value=sqroot(index); break;
             case 3 : value=cube(index);   break;
             default: value=0;
          }
          cout << index << "\t" << value << endl;
       }
    }
    
    float square(int x)
    {
       return (float)(x * x);
    }
    float sqroot(int x)
    {
       return sqrt((float) x);
    }
    float cube(int x)
    {
       return (float) (x*x*x);
    }
    

  7. For output we get:
    Table of Squares
    1       1
    3       9
    5       25
    7       49
    9       81
    
    Table of Square Roots
    2       1.41421
    5       2.23607
    8       2.82843
    11      3.31662
    14      3.74166
    
    Table of Cubes
    3       27
    6       216
    9       729
    

  8. By using pointers to functions we can change table so that we do not have to rewrite for every change. To use pointers to a function our code looks like:
    //
    //  Pointers to functions
    //
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    void table(string,int,int,int,float(*)(int));
    float square(int);
    float sqroot(int);
    float cube(int);
    
    int main()
    {
       table("Squares",1,10,2,square);
       table("Square Roots",2,15,3,sqroot);
       table("Cubes",3,12,3,cube);
       system("pause");
       return 0;
    }
    
    void table(string text, int start, int end, int increment, float (*function)(int))
    {
    //
    // pre - none
    // post - table of a math function
    //         text for heading
    //         start, end, increment for series
    //         function pointer to the result function
       int   index;
       float value;
       cout << endl << "Table of " << text << endl;
       for(index=start; index < end ; index+=increment) {
          value=(*function)(index);
          cout << index << "\t" << value << endl;
       }
    }
    
    float square(int x)
    {
    return (float)(x * x);
    }
    float sqroot(int x)
    {
    return sqrt((float) x);
    }
    float cube(int x)
    {
    return (float) (x*x*x);
    }
    

  9. Giving us the expected result:
    
    Table of Squares
    1       1
    3       9
    5       25
    7       49
    9       81
    
    Table of Square Roots
    2       1.41421
    5       2.23607
    8       2.82843
    11      3.31662
    14      3.74166
    
    Table of Cubes
    3       27
    6       216
    9       729
    

  10. Then to add another function table all we need to do is write the function and change main. We do not need to chnage the table function. The primary use of this technique will be to incluse "callback" functions in our object implementations.
    //
    //  Pointers to functions
    //
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    void table(string,int,int,int,float(*)(int));
    float square(int);
    float sqroot(int);
    float cube(int);
    float sumofdigits(int);
    
    int main()
    {
       table("Squares",1,10,2,square);
       table("Square Roots",2,15,3,sqroot);
       table("Cubes",3,12,3,cube);
       table("Sum of the Digits",1,5,1,sumofdigits);
       system("pause");
       return 0;
    }
    
    void table(string text, int start, int end, int increment, float (*function)(int))
    {
    //
    // pre - none
    // post - table of a math function
    //         text for heading
    //         start, end, increment for series
    //         function pointer to the result function
       int   index;
       float value;
       cout << endl << "Table of " << text << endl;
       for(index=start; index < end ; index+=increment) {
          value=(*function)(index);
          cout << index << "\t" << value << endl;
       }
    }
    
    float square(int x)
    {
       return (float)(x * x);
    }
    float sqroot(int x)
    {
       return sqrt((float) x);
    }
    float cube(int x)
    {
       return (float) (x*x*x);
    }
    float sumofdigits(int x)
    {
       return (float)((x*x+x)/2);
    }
    

  11. Our output now looks like:
    
    Table of Squares
    1       1
    3       9
    5       25
    7       49
    9       81
    
    Table of Square Roots
    2       1.41421
    5       2.23607
    8       2.82843
    11      3.31662
    14      3.74166
    
    Table of Cubes
    3       27
    6       216
    9       729
    
    Table of Sum of the Digits
    1       1
    2       3
    3       6
    4       10