Navigation



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:

int nArray[10];

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:

int foo();

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:

// pFoo is a pointer to a function that takes no arguments and returns an integer
int (*pFoo) ();

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:

int foo()
{
}

int goo()
{
}

int main()
{
    int (*pFoo)() = foo; // pFoo points to function foo()
    pFoo = goo; // pFoo now points to function goo()
    return 0;
}

One common mistake is to do this:

pFoo = goo();

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:

// function prototypes
int foo();
double goo();
int hoo(int nX);

// function pointer assignments
int (*pFcn1)() = foo; // okay
int (*pFcn2)() = goo; // wrong -- return types don't match!
double (*pFcn3)() = goo; // okay
pFcn1 = hoo; // wrong -- pFcn1 has no parameters, but hoo() does
int (*pFcn3)(int) = hoo; // okay

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:

int foo(int nX)
{
}

int (*pFoo)(int) = foo; // assign pFoo to foo()

(*pFoo)(nValue); // call function foo(nValue) through pFoo.

The second way is via implicit dereference:

int foo(int nX)
{
}

int (*pFoo)(int) = foo; // assign pFoo to foo()

pFoo(nValue); // call function foo(nValue) through pFoo.

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:

void SelectionSort(int *anArray, int nSize)
{
    using namespace std;
    for (int nStartIndex= 0; nStartIndex < nSize; nStartIndex++)
    {
        int nBestIndex = nStartIndex;

        // Search through every element starting at nStartIndex+1
        for (int nCurrentIndex = nStartIndex + 1; nCurrentIndex < nSize; nCurrentIndex++)
        {
            // Note that we are using the user-defined comparison here
            if (anArray[nCurrentIndex] < anArray[nBestIndex]) // COMPARISON DONE HERE
                nBestIndex = nCurrentIndex;
        }

        // Swap our start element with our best element
        swap(anArray[nStartIndex], anArray[nBestIndex]);
    }
}

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:

bool Ascending(int nX, int nY)
{
    return nY > nX;
}

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

void SelectionSort(int *anArray, int nSize)
{
    using namespace std;
    for (int nStartIndex= 0; nStartIndex < nSize; nStartIndex++)
    {
        int nBestIndex = nStartIndex;

        // Search through every element starting at nStartIndex+1
        for (int nCurrentIndex = nStartIndex + 1; nCurrentIndex < nSize; nCurrentIndex++)
        {
            // Note that we are using the user-defined comparison here
            if (Ascending(anArray[nCurrentIndex], anArray[nBestIndex])) // COMPARISON DONE HERE
                nBestIndex = nCurrentIndex;
        }

        // Swap our start element with our best element
        swap(anArray[nStartIndex], anArray[nBestIndex]);
    }
}

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:

bool (*pComparison)(int, int);

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:

#include <algorithm> // for swap

// Note our user-defined comparison is the third parameter
void SelectionSort(int *anArray, int nSize, bool (*pComparison)(int, int))
{
    using namespace std;
    for (int nStartIndex= 0; nStartIndex < nSize; nStartIndex++)
    {
        int nBestIndex = nStartIndex;

        // Search through every element starting at nStartIndex+1
        for (int nCurrentIndex = nStartIndex + 1; nCurrentIndex < nSize; nCurrentIndex++)
        {
            // Note that we are using the user-defined comparison here
            if (pComparison(anArray[nCurrentIndex], anArray[nBestIndex])) // COMPARISON DONE HERE
                nBestIndex = nCurrentIndex;
        }

        // Swap our start element with our best element
        swap(anArray[nStartIndex], anArray[nBestIndex]);
    }
}

// Here is a comparison function that sorts in ascending order
// (Note: it's exactly the same as the previous Ascending() function)
bool Ascending(int nX, int nY)
{
    return nY > nX;
}

// Here is a comparison function that sorts in descending order
bool Descending(int nX, int nY)
{
    return nY < nX;
}

// This function prints out the values in the array
void PrintArray(int *pArray, int nSize)
{
    for (int iii=0; iii < nSize; iii++)
        cout << pArray[iii] << " ";
    cout << endl;
}

int main()
{
    using namespace std;

    int anArray[9] = { 3, 7, 9, 5, 6, 1, 8, 2, 4 };

    // Sort the array in descending order using the Descending() function
    SelectionSort(anArray, 9, Descending);
    PrintArray(anArray, 9);

    // Sort the array in ascending order using the Ascending() function
    SelectionSort(anArray, 9, Ascending);
    PrintArray(anArray, 9);

    return 0;
}

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:

bool EvensFirst(int nX, int nY)
{
        // if nX is not even and nY is, nY goes first
	if ((nX % 2) && !(nY % 2))
		return false;

        // if nX is even and nY is not, nX goes first
	if (!(nX % 2) && (nY % 2))
		return true;

        // otherwise sort in Ascending order
	return Ascending(nX, nY);
}

int main()
{
    using namespace std;

    int anArray[9] = { 3, 7, 9, 5, 6, 1, 8, 2, 4 };

    SelectionSort(anArray, 9, EvensFirst);
    PrintArray(anArray, 9);

    return 0;
}

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:

typedef bool (*pfcnValidate)(int, int);

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:

bool Validate(int nX, int nY, bool (*pfcn)(int, int));

You can do this:

bool Validate(int nX, int nY, pfcnValidate pfcn)

Which reads a lot nicer!

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

36 comments to 7.8 — Function Pointers

  • Ainsley

    hi i enjoyed the read

  • Renu

    Syntax of typedef is:
    typedef type alias name;

    How does that map to:
    typedef bool (*pfcnValidate)(int, int);

    This seems complex.

    Renu

    • This is one of the really ugly parts of C++. Basically, the type is a pointer to a function returning a bool and taking 2 int parameters, and the name of the typedef is pfcnValidate.

      I suspect they did the syntax this way to mimic the way actual function declarations look, but I agree that it doesn’t map to the typedef syntax in a very intuitive manner. It’s one of those things I have to look up how to do every time I need to do it… but that’s still better than not using typedefs at all.

  • shyan

    typedef of function pointer looks complex.
    no typedef variable. how it assumed that pfcnVlidate is typedef… confuse

    shyam

  • [...] 2007 Prev/Next Posts « 7.6 — Function overloading | Home | 7.8 — Function Pointers » Monday, August 6th, 2007 at 4:38 [...]

  • Stuart
    bool EvensFirst(int nX, int nY)
    {
            // if nX is even and nY is not, nX goes first
        if ((nX % 2) && !(nY % 2))
            return false;   
    
            // if nX is not even and nY is, nY goes first
        if (!(nX % 2) && (nY % 2))
            return true;   
    
            // otherwise sort in Ascending order
        return Ascending(nX, nY);
    }

    How is bool working here? How is the return false and return true working to return the integers in different orders?

    • Stuart

      I get it now, after rewriting the EvensFirst function to this:

      bool EvensFirst(int nX, int nY)
      {
      	// if nX is even and nY is not, nX goes first
      	if ((nX % 2 == 0) && !(nY % 2) == 0)
      		return true;
      
      	// if nX is not even and nY is, nY goes first
      	if (!(nX % 2 == 0) && (nY % 2 == 0))
      		return false;
      
      	// otherwise sort in Ascending order
      	return Ascending(nX, nY);
      }

      I got mixed up and didn’t realize that nX % 2 actually means that nX is NOT divisible by 2 and !nX % 2 means that it IS divisible by 2.

  • Simon

    bool EvensFirst(int nX, int nY)

    Alex your comments are incorrect in this function as pointed out by Stuart.

    You can either change the if statements to match the comments or change the comments to match the statements.

    You need to change the 1st comment with the second, and vice versa .
    Stuart’s changes also correct the anomalies.

    Regards
    Simon

  • [...] 2007 Prev/Next Posts « 7.8 — Function Pointers | Home | 7.10 — Recursion » Friday, August 10th, 2007 at 4:56 [...]

  • fernando

    Should the function call not return some value ?

    1.int foo(int nX)
    2.{
    3.}
    4.
    5.int (*pFoo)(int) = foo; // assign pFoo to foo()
    6.
    7.(*pFoo)(nValue); // call function foo(nValue) through pFoo.
    
    The second way is via implicit dereference:
    view source
    print?
    1.int foo(int nX)
    2.{
    3.}
    4.
    5.int (*pFoo)(int) = foo; // assign pFoo to foo()
    6.
    7.pFoo(nValue); // call function foo(nValue) through pFoo.
    
  • Ryan

    You left two things out of your full example.

    1. You forgot to include iostream needed to define the ‘cout’

    2.

    void PrintArray(int *pArray, int nSize)
    {
        for (int iii=0; iii < nSize; iii++)
            cout << pArray[iii] << " ";
        cout << endl;
    }
    

    You forgot to add ‘using namespace std;’ thus cout doesn’t work here.

  • ROCKIN!!! Been trying to get my head around function pointers for ages!!!

    Now I get it!!!

    Probably forget again tomorrow, but at least I can come here and look it up again!

    THANK YOU!!!!

  • Its strange you didn’t cover pointers to member functions…anyways great tutorial overall.

  • I have a problem:

    I write a class.

    There is a function, member of this class.

    There is another function, member of this class, takes a “function pointer” as parameter.

    Inside this class there is also a third function and it calls the second function with a function pointer to first function as parameter.

    Here is the code:

    #include <iostream>
    using namespace std;
    
    class Kas {
    
    	 public:
    	  int ada;
    
    	  int firstfunction (int);
    
    	  void secondfunction (int (*ptofunction)(int), int t);
    
    	  void thirdfunction ();
    
    };
    
    void Kas::secondfunction ( int (*ptofunction)(int),int t){
    	 (*ptofunction)(t);
    };
    
    int Kas::firstfunction (int s) {
    	 return ada+s;
    };
    
    void Kas::thirdfunction (){
    	 secondfunction(firstfunction,3);	//The problem is here!!
    };
    
    int main () {
    
        Kas den;
        den.thirdfunction();
        cout<<den.ada<<"\n";
    
        system("PAUSE");
        return 0;
    
    }
    

    how can I call the second function?

  • Solved !

    void Kas::secondfunction ( int (Kas::*ptofunction)(int),int t){
    	 (this->*ptofunction)(t);
    };
    
    void Kas::thirdfunction (){
    	 secondfunction(&Kas::firstfunction,3);
    };
    
    • Ravi

      Hi,

      Nice way of explaining the Function pointers.

      I tried to compile the code given up and I am still getting this error

      error: prototype for ‘void Kas::secondfunction(int (Kas::*)(int), int)’ does not match any in class ‘Kas’
      error: candidate is: void Kas::secondfunction(int (*)(int), int)

  • awsome post..i love it.. :)

  • Murka

    Member functions are sometimes a pain to use, but typedefs make even such fugly syntax readable.

    Example:

    typedef std::string (playerInfo::*memfuncptr)();
    //Function prototype
    memfuncptr strToMfptr(std::string &strInput);
    

    So remember, typedefs are your friend. I still haven’t found out how to write the above without one, but am interested how it would look.

  • Martin

    Hi, could someone help me with program problem ?
    I have code

    
    while(1)  {
        cout << "Write string: " ;
        getline(cin,input_string);
        cout << "Write number: ";
        cin << input_number;
    ...
    }
    

    Program should get input from user and make some actions, and then want again new input and again and again…In first loop everything works good, but in the second loop getline() dont read string, i get output:

    Write string: Write number :
    

    cin wants me to enter number , but getline was skipped, do u know why ?

  • Blaji

    Hi, I would like to add some more points. How do we declare a pointer to a function which returns a pointer to a function ? (function pointer returning function pointer). Here we go.. Explained by sample code below. Hope its clear.

    void foo()
    {
    printf(“Im foo”);
    }

    typedef void (*retType)();

    retType FuncRetFuncPtr()
    {
    printf(“FuncRetFuncPtr calledn”);
    return foo; //returning function pointer
    }

    main()
    {
    retType (*fptr)() = FuncRetFuncPtr;
    void (*catchfoo)() = fptr(); //catchfoo-holds return val of FuncRetFuncPt

    catchfoo(); //prints “im foo”. for confirmation :)
    }

  • Srivatsan

    hi Alex,

    What exactly does it mean when you say the name of the function is a pointer?? A pointer to a variable, I understand, holds the address where the variable is stored. What is stored in the address that the name of the function points to?

    Great tutorial. Thank you.

  • george

    Is function pointer the only way to pass a function as a parameter to another function?

  • SJ

    Hi,
    Will you please explain me constant function or constant member function.
    e.g.

    int fun1() const;
    Will you please explain me where and why we need to use this? With example.

  • Matt

    Great tutorials Alex although all this pointer stuff is pretty confusing. I’d like to see some questions at the end of some of these though. I would have a better understanding of the concepts and a memory of the syntax if I had to do some of this myself; a suggestion if you have time.

  • [...] KNOWLEDGE FOR THIS PROGRAM Integer Arrays Character Arrays BubbleSort Pointers Function Pointers – What Are They? Memcpy Sizeof [...]

  • Sergey

    Thank you! You can show how to enjoy the programming in language considered one of most complex (and, sometimes, even “ugly” in syntax). Ever considered to publish it in hard-copy?

  • mohsenhs82

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

    merry Xmas.

  • It’s like magic . Great !!!

  • [...] to display all of the contents within each array. The implementation revolves around using a simple function pointer and arrays of void [...]

  • 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? ^^

  • 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);

You must be logged in to post a comment.