Function pointers are one of those odd elements of C++ that don't always have an obvious application. Since I am of a math background, I'm going to look at some ways that function pointers can be useful. One of the peculiar properties of math is that, when you advance far enough, you start looking at functions as things to be worked on. Some practical examples include:
Composition of functions: f(g(h(x))) Derivatives of functions Integrals of functions Arrays of functions
In physics, there are also a variety of applications of the above, plus various other applications of principles where the exact function is not known in advance. One of the basic ideas that appears in physics is the concept of an average rate of change. The basic idea is this: average velocity is the average rate of change of position as a function of time: (pos(final)-pos(start))/(final-start). Average acceleration is the average rate of change of velocity (same formula, use vel instead of pos). Calculus is obsessed with this concept.
In C++, we can use a pointer to a function to implement this concept with a single function. You declare a pointer to a function like this:
double f(double); //function that takes a double and returns a double double (*fptr)(double); //pointer to a function that takes a double and returns a double double *g(double); //function that takes a double and returns a pointer to a double fptr = &f //valid g = &f //error, g is not a pointer fptr = &g //error g and fptr return different types
Given this idea, we could then create a function that accepts a function pointer as a parameter, and uses the formula for calculating average velocity with the function it received.
An example of a program using this concept is avevel.cpp:
#include <iostream> #include <cmath> const double pi = 3.14159265358979323846264338327950288419716939937510; typedef double(* FCT_PNTR)(double); double avechange(FCT_PNTR f, double start,double end) { if (start == end) return 0.0; else return (f(end) - f(start))/(end - start); } double square(double x) { return x*x; } double cube(double x) { return x*x*x; } int main() { std::cout<<"sin from 0 to pi: "<<avechange(&sin,0.0,pi)<<"\n"; std::cout<<"cos from 0 to pi: "<<avechange(&cos,0.0,pi)<<"\n"; std::cout<<"square from 0 to 2: "<<avechange(&square,0.0,2.0)<<"\n"; std::cout<<"square from 2 to 0: "<<avechange(&square,2.0,0.0)<<"\n"; std::cout<<"square from -2 to 0: "<<avechange(&square,-2.0,0.0)<<"\n"; std::cout<<"square from 0 to -2: "<<avechange(&square,0.0,-2.0)<<"\n"; std::cout<<"square from -2 to 2: "<<avechange(&square,-2.0,2.0)<<"\n"; std::cout<<"square from 0 to 0: "<<avechange(&square,0.0,0.0)<<"\n"; std::cout<<"cube from 0 to 2: "<<avechange(&cube,0.0,2.0)<<"\n"; std::cout<<"cube from 2 to 0: "<<avechange(&cube,2.0,0.0)<<"\n"; std::cout<<"cube from -2 to 0: "<<avechange(&cube,-2.0,0.0)<<"\n"; std::cout<<"cube from 0 to -2: "<<avechange(&cube,0.0,-2.0)<<"\n"; std::cout<<"cube from -2 to 2: "<<avechange(&cube,-2.0,2.0)<<"\n"; std::cout<<"cube from 0 to 0: "<<avechange(&cube,0.0,0.0)<<"\n"; }
In the above code, avechange() will vary its behavior based on the function it was told to use when doing the average. It may look slightly strange to pass a function name as a parameter, but it works. The output for the above code is:
sin from 0 to pi: 3.89804e-17 cos from 0 to pi: -0.63662 square from 0 to 2: 2 square from 2 to 0: 2 square from -2 to 0: -2 square from 0 to -2: -2 square from -2 to 2: 0 square from 0 to 0: 0 cube from 0 to 2: 4 cube from 2 to 0: 4 cube from -2 to 0: 4 cube from 0 to -2: 4 cube from -2 to 2: 4 cube from 0 to 0: 0