- Modern C++:Efficient and Scalable Application Development
- Richard Grimes Marius Bancila
- 475字
- 2021-06-10 18:28:08
Declaring function pointers
The last section highlights how easy it is to get the address of a function: you just use the name of the function without the parentheses:
void *pv = get_status;
The pointer pv is only of mild interest; you now know where in memory the function is stored, but to print this address you still need to cast it to an integer. To make the pointer useful, you need to be able to declare a pointer through which the function can be called. To look at how to do this, let's go back to the function prototype:
int get_status()
The function pointer must be able to call the function passing no parameters and expecting a return value of an integer. The function pointer is declared like this:
int (*fn)() = get_status;
The * indicates that the variable fn is a pointer; however, this binds to the left, so without the parentheses surrounding *fn the compiler would interpret this to mean that the declaration is for an int* pointer. The rest of the declaration indicates how this function pointer is called: taking no parameters and returning an int.
Calling through a function pointer is simple: you give the name of the pointer where you would normally give the name of the function:
int error_value = fn();
Note again how important the parentheses are; they indicates that the function at the address held in the function pointer, fn, is called.
Function pointers can make code look rather cluttered, especially when you use them to point to templated functions, so often code will define an alias:
using pf1 = int(*)();
typedef int(*pf2)();
These two lines declare aliases for the type of the function pointer needed to call the get_status function. Both are valid, but the using version is more readable since it is clear that pf1 is the alias being defined. To see why, consider this alias:
typedef bool(*MyPtr)(MyType*, MyType*);
The type alias is called MyPtr and it is to a function that returns a bool and takes two MyType pointers. This is much clearer with using:
using MyPtr = bool(*)(MyType*, MyType*);
The tell-tale sign here is the (*), which indicates that the type is a function pointer because you are using the parenthesis to break the associatively of the *. You can then read outwards to see the prototype of the function: to the left to see the return type, and to the right to get the parameter list.
Once you have declared an alias, you can create a pointer to a function and call it:
using two_ints = void (*)(int, int);
void do_something(int l, int r){/* some code */}
void caller()
{
two_ints fn = do_something;
fn(42, 99);
}
Notice that, because the two_ints alias is declared as a pointer, you do not use a * when declaring a variable of this type.