Search

7.8 — Function Pointers

Function pointers are an advanced topic, and this section can be safely skipped or skimmed by those only looking for C++ basics.

In the lesson on pointers, you learned that a pointer is a variable that holds the address of another variable. Function pointers are similar, except that instead of pointing to variables, they point to functions!

Consider the case of an array:

As you now know, nArray is actually a constant pointer to a 10 element array. When we dereference the pointer (either by *nArray or nArray[nIndex]), the appropriate array element is returned.

Now consider the following function:

If you guessed that foo is actually a constant pointer to a function, you are correct. When a function is called (via the () operator), the function pointer is dereferenced, and execution branches to the function.

Just like it is possible to declare a non-constant pointer to a variable, it’s also possible to declare a non-constant pointer to a function. The syntax for doing so is one of the ugliest things you will ever see:

The parenthesis around *pFoo are necessary for precedence reasons, as int *pFoo() would be interpreted as a function named pFoo that takes no parameters and returns a pointer to an integer.

In the above snippet, pFoo is a pointer to a function that has no parameters and returns an integer. pFoo can “point” to any function that matches this signature.

Assigning a function to a function pointer

There are two primary things that you can do with a pointer to a function. First, you can assign a function to it:

One common mistake is to do this:

This would actually assign the return value from a call to function goo() to pFoo, which isn’t what we want. We want pFoo to be assigned to function goo, not the return value from goo(). So no parenthesis are needed.

Note that the signature (parameters and return value) of the function pointer must match the signature of the function. Here is an example of this:

Calling a function using a function pointer

The second thing you can do with a function pointer is use it to actually call the function. There are two ways to do this. The first is via explicit dereference:

The second way is via implicit dereference:

As you can see, the implicit dereference method looks just like a normal function call -- which is what you’d expect, since normal function names are pointers to functions anyway! However, some older compilers do not support the implicit dereference method, but all modern compilers should.

Why use pointers to functions?

There are several cases where pointers to function can be of use. One of the most common is the case where you are writing a function to perform a task (such as sorting an array), but you want the user to be able to define how a particular part of that task will be performed (such as whether the array is sorted in ascending or descending order). Let’s take a closer look at this problem as applied specifically to sorting, as an example that can be generalized to other similar problems.

All sorting algorithms work on a similar concept: the sorting algorithm walks through a bunch of numbers, does comparisons on pairs of numbers, and reorders the numbers based on the results of those comparisons. Consequently, by varying the comparison (which can be a function), we can change the way the function sorts without affecting the rest of the sorting code.

Here is our selection sort routine from a previous lesson:

Now, let’s replace that comparison with a function to do the comparison. Because our comparison function is going to compare two integers and return a boolean value, it will look something like this:

And here’s our selection sort routine using the Ascending() function to do the comparison:

In order to let the caller decide how the sorting will be done, instead of using our own hard-coded comparison function, we’ll allow the caller to provide his own sorting function! This is done via a function pointer.

Because the caller’s comparison function is going to compare two integers and return a boolean value, a pointer to such a function would look something like this:

So, we’ll allow the caller to pass our sort routine a pointer to their desired comparison function as the third parameter, and then we’ll use the caller’s function to do the comparison.

Here’s a full example of a selection sort that uses a function pointer parameter to do a user-defined comparison, along with an example of how to call it:

This program produces the result:

9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9

Is that cool or what? We’ve given the caller the ability to control how our selection sort does it’s job.

The caller can even define his own “strange” comparison functions:

The above snippet produces the following result:

2 4 6 8 1 3 5 7 9

As you can see, using a function pointer in this context provides a nice way to allow a caller to “hook” it’s own functionality into something you’ve previously written and tested, which helps facilitate code reuse! Previously, if you wanted to sort one array in descending order and another in ascending order, you’d need multiple version of the sort routine. Now you can have one version that can sort any way the caller desires!

Making function pointers pretty with typedef

Let’s face it -- the syntax for pointers to functions is ugly. However, typedefs can be used to make pointers to functions look more like regular variables:

This defines a typedef called “pfcnValidate” that is a pointer to a function that takes two ints and returns a bool.

Now instead of doing this:

You can do this:

Which reads a lot nicer!

7.9 -- The stack and the heap
Index
7.7 -- Default parameters

31 comments to 7.8 — Function Pointers

  • Yisong Zhu

    Excellent read for learning function pointer. Thank you.

    I don't think that a temporary index "nBestIndex" is needed. A bubbleSort function could be written like this:

    void bubbleSort(int *arr,int len,compare cmp){
    int start,curr;
    for(start=0;start<len;start++){
    for(curr=start+1;curry);
    }

    bool descentCmp(int x,int y){
    return (y>x);
    }

    bool evenFirstAscent(int x,int y){
    //first is uneven, second is even
    if((x%2) && (!(y%2))){
    return true;
    }
    //first is even, second is uneven
    if(!(x%2) && (y%2)){
    return false;
    }
    //otherwise
    return ascentCmp(x,y);
    }

    bool oddFirstAscent(int x,int y){
    //first is even, second is uneven
    if(!(x%2) && (y%2)){
    return true;
    }
    //first is uneven, second is even
    if((x%2) && (!(y%2))){
    return false;
    }
    //otherwise
    return ascentCmp(x,y);
    }

    //on calling part
    compare *cmp; //declaration under function type
    cin>>choice;
    switch(choice){
    case 0: cmp=ascentCmp;
    break;
    case 1: cmp=descentCmp;
    break;
    case 2: cmp=evenFirstAscent;
    break;
    case 3: cmp=oddFirstAscent;
    break;
    }
    bubbleSort(myArr,size,cmp);

  • NoMercy235

    Hello! I have tried making an application that can sum/substract/divide/multiply two numbers based on the alogrythm Alex made.
    This is how it looks: (I am using VS 2010)
    #include "stdafx.h"
    #include

    using namespace std;

    int a,b;

    int Operation(int x, int y , int (*pSign)(int , int)){
    return pSign(x,y);
    }

    int Multiply(int x, int y){
    return x*y;
    }

    int Add(int x, int y){
    return x+y;
    }

    int Substract(int x, int y){
    return x-y;
    }

    int Divide(int x, int y){
    return x/y;
    }

    int main(){

    cin>>a>>b;
    cout<<Operation(a , b, Multiply);
    cout<<Operation(a , b, Add);
    cout<<Operation(a , b, Substract);
    cout<<Operation(a , b, Divide);

    return 0;
    }

    However , when i run it , nothing shows up. Not even the return message , that's why I guess it enters in some kind of loop somewhere.
    Can someone give me some advice? ^^

  • It's like magic . Great !!!

  • mohsenhs82

    Hi Alex
    Great job, Great Tutorial, and an Excellent example.

    merry Xmas.

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">