C++ pointers to functions and callbacks

How to create and use function pointers, including using them in callbacks

As with a data object, the code generated for a function body is placed in memory, so it has an address which means we can have a pointer to it.

Unlike data object pointers, function pointers do not allows us to modify the function code. There are only two things we can do with a function pointer: call it and take its address.

The pointer obtained by taking the address of a function can be used to call the function.

Declaring and using a pointer to a function

In the example code bellow a pointer is set with the address of a function and then used to call the function.

#include <iostream>
#include <string>

// function implementation
void do_something(string message)
{
    std::cout << message << std::endl;
}

// declaring a pointer to functions as the one above
void (*fp)(string);

// call the function using the pointer from another function
void do_something_and_more()
{
    std::cout << "Let's call the function using the pointer" << std::endl;
    fp("upii! it runs");
    std::cout << "Done" << std::endl;
}

int main(void)
{
    // associating the function address with the function pointer
    fp = &do_something;

    do_something_and_more();
}

Pointers to functions have arguments declared just like the functions themselves. That’s why the pointer fp was declared as returning void and with a string parameter.

Note that using * for deferencing and & to get the address of a function is optional. Consider the following code example.

// fp1 and fp2 both point to do_something function
void (*fp1)(int) = &do_something;
void (*fp2)(int) = do_something;

fp1("it's me!"); // prints "it's me!"
(*fp1)("it's me again!"); // prints "it's me again!"

fp1("it's me!"); // prints "it's me!"
(*fp1)("it's me again!"); // prints "it's me again!"

Function pointers and callbacks

A typical use for function pointers is to pass a callback function as the parameter of another function.

Imagine you have a function that should call another function, let’s call this other function the callback, which is provided as a parameter. By having the callback function as a parameter of the first function allows to call different functions on different calls of the first function. Confused? Don’t worry, it will become clearer in the code example.

A way to implement the callback mechanism is by using a function pointer that is passed as a parameter of another function. Let’s look at a code example.

#include <iostream>
#include <string>

// the callback function
void do_this_when(const char* message)
{
    std::cout << "Message: " << message << std::endl;
}

// the function that will use the callback
void i_will_call_you(void (*fp)(const char* message))
{
    fp("upii");
}

int main(void)
{
    // calling the fucntion
    i_will_call_you(do_this_when); // prints "Message: upii"
    i_will_call_you(&do_this_when); // also prints "Message: upii"
}

Use cases to this mechanism is in asynchronous programming, where you want to run some code when some event happens, and in libraries.

0%