Basic knowledge of function pointer
The address of a function is the starting address of the memory where its machine language code is stored.
How to use function pointers:
- Get the address of the function
- Declare a function pointer
- Use function pointers to call functions
Get function address
Get the function address, just use the function name.
think(); // function think // Function address process(think); //Pass the address of the think function process(think()); // Pass the return value of the think function
Declare function pointer
Declaring a function pointer is the same as declaring a data type pointer. You must specify the function type pointed to by the pointer, that is, the return type and the characteristic (parameter list).
double pam(int); // prototype function double (*pf)(int); // Declare function pointer void estimate(int lines, double (*pf)(int)); // Declared in parameter
It can be understood here that (* pf) replaces pam,
(* pf) is the function name,
pf is the function pointer.
Note the parentheses:
double (*pf)(int); // Function pointer double *pf(int); // pf is a function that returns a double pointer
Function pointer call function
(* pf) plays the same role as the function name, which can be regarded as the function name
double pam(int); double (*pf)(int); pf = pam; // pf points to the pam() function double x = pam(4); // Function name call double y = (*pf)(5); // Function pointer call actually, C++Allow direct use pf call double y = pf(5); // Function pointer call, the effect is the same as above
Example:
// fun_ptr.cpp -- pointers to functions #include <iostream> double betsy(int); double pam(int); // second argument is pointer to a type double function that // takes a type int argument void estimate(int lines, double (*pf)(int)); int main() { using namespace std; int code; cout << "How many lines of code do you need? "; cin >> code; cout << "Here's Betsy's estimate:\n"; estimate(code, betsy); cout << "Here's Pam's estimate:\n"; estimate(code, pam); return 0; } double betsy(int lns) { return 0.05 * lns; } double pam(int lns) { return 0.03 * lns + 0.0004 * lns * lns; } void estimate(int lines, double (*pf)(int)) { using namespace std; cout << lines << " lines will take "; cout << (*pf)(lines) << " hour(s)\n"; }
Explore function pointers in depth
Take a look at the function prototypes below. They have the same return type and signature
const double * f1(const double ar[], int n); const double * f2(const double [], int n); const double * f3(const double *, int n);
The feature marks look different, but they are actually the same
If you need to declare a function pointer pointing to the above function, such as the pointer name pa, you can replace the function name with (* pa).
const double * (*p1)(const double *, int n); Initialize while declaring const double * (*p1)(const double *, int n) = f1; utilize C++11 Automatic type inference can simplify code auto p2 = f2;
Next, let's look at the following statement:
cout << (*p1)(av, 3) << ": " << *(*p1)(av, 3) << endl; cout << p2(av, 3) << ": " << *p2(av, 3) << endl;
It can be seen from the previous introduction of basic knowledge that (* p1)(av, 3) and p2(av, 3) are the calls of functions f1() and f2() respectively, and av (double array) and 3 are parameters.
The return value type of the function const double * (i.e. the address of the return value), plus a *, you can get the actual return value.
(*p1)(av, 3) // Call f1() to return an address p2(av, 3) // Call f2() to return an address *(*p1)(av, 3) // Return value of f1() *p2(av, 3) // Return value of
Function pointer array
Given the need to use three functions, it is much more convenient to declare an array of function pointers. The statement is as follows:
const double * (*pa[3])(const double * , int) = {f1, f2, f3}; // Declaration and initialization
**Note: * operator [] takes precedence over, pa[3] is an array containing three elements, and * pa[3] is an array containing three pointers.
Can I use auto here? No. Auto can only be used for single value initialization, not initialization list. However, after declaring the array pa, you can use Auto to declare arrays of the same type.
auto pb = {f1, f2, f3}; // error auto pb = pa; // correct
pa[i] and pb[i] represent pointers in an array, so you can use any function call notation for them
const double * px = pa[0](av, 3); //Call function const double * py = (*pb[1])(av, 3); // Call function
To get the actual return value, you can use the operator*
double x = *pa[0](av, 3); double y = (*pb[1])(av, 3);
Pointer to array of function pointers
You can also create pointers to the entire array. First, the array name is a pointer (pointing to the first element), and pa contains three function pointers, so the array name pa is a pointer to the function pointer. That is, pa is a pointer to a pointer. In addition, because it is a single value initialization, you can use auto.
auto pc = &pa; // Using c+11 characteristics
You can declare it yourself without using auto. At this point, you need to declare that this is a pointer, not an array, which means you need to add an operator * somewhere.
*pd[3] indicates that pd is an array containing three pointers
*(pd)[3] represents pd a pointer to an array containing three elements
Therefore, my statement is as follows
const double * (*pa[3])(const double *, int) = {f1, f2, f3}; const double * (*(*pd)[3])(const double *, int) = &pa; // Change pa to (* pb) ====================== const double * // return type (const double * , int) // For parameter list (*pd)[3] // pd is a pointer to an array of three elements (*(*pd)[3]) // pd is a pointer to an array of three pointers const double * (*(*pd)[3])(const double * , int) // pd is a pointer to an array of three function pointers
There are two ways to call functions
(*(*pd)[3])(av , 3); // or (*pd)[3](av , 3);
At this time, the return address of the function, that is, the pointer. To obtain the return value of the calling function, you can use the operator*
*(*(*pd)[3])(av , 3); // or *(*pd)[3](av , 3);
Note: the difference between pa and & pa. pa is an array name. Namely & pa [0]
**&pa == *pa == pa[0]
Example:
// arfupt.cpp -- an array of function pointers #include <iostream> // various notations, sam signatures const double* f1(const double ar[], int n); const double* f2(const double[], int n); const double* f3(const double*, int); int main() { using namespace std; double av[3] = { 1112.3, 1542.6, 2227.9 }; // pointer to a function const double* (*p1)(const double*, int) = f1; // Pointer F1 to function declaration () auto p2 = f2; // c++11 automatic type deduction cout << "Using pointers to functions:\n"; cout << " Address Value\n"; cout << (*p1)(av, 3) << ": " << *(*p1)(av, 3) << endl; // Return value address: return value //pa an array of pointers const double* (*pa[3])(const double*, int) = {f1, f2, f3}; // Function pointer array auto pb = pa; cout << "\nUsing an array of pointers to functions:\n"; cout << " Address Value\n"; for (int i = 0; i < 3; i++) { cout << pa[i](av, 3) << ": " << *pa[i](av, 3) << endl; } cout << "\nUsing an array of pointers to functions:\n"; cout << " Address Value\n"; for (int i = 0; i < 3; i++) { cout << pb[i](av, 3) << ": " << *pb[i](av, 3) << endl; } cout << "\nUsing an array of pointers to functions:\n"; cout << " Address Value\n"; // a easy to declare pc auto pc = &pa; // Pointer to function pointer array cout << (*pc)[0](av, 3) << ": " << *(*pc)[0](av, 3) << endl; // a hard way to declare pd const double* (*(*pd)[3])(const double*, int) = &pa; // Pointer to function pointer array const double* pdb = (*pd)[1](av, 3); cout << pdb << ": " << *pdb << endl; cout << (*(*pd)[2])(av, 3) << ": " << *(*(*pd)[2])(av, 3) << endl; return 0; } const double* f1(const double ar[], int n) { return ar; } const double* f2(const double ar[], int n) { return ar+1; } const double* f3(const double ar[], int) { return ar + 2; }
Output results
Using pointers to functions: Address Value 000000370F72F908: 1112.3 Using an array of pointers to functions: Address Value 000000370F72F908: 1112.3 000000370F72F910: 1542.6 000000370F72F918: 2227.9 Using an array of pointers to functions: Address Value 000000370F72F908: 1112.3 000000370F72F910: 1542.6 000000370F72F918: 2227.9 Using an array of pointers to functions: Address Value 000000370F72F908: 1112.3 000000370F72F910: 1542.6 000000370F72F918: 2227.9
Simplify with typedef
typedef is used to create type aliases, which can be used to create aliases for function pointer types
typedef const double * (*p_fun)(const double *, int); // p_fun now a type name p_fun p1 = f1; // p1 points to the f1() function //Function pointer array p_fun pa[3] = {f1, f2, f3}; // pa an array of 3 function pointers p_fun (*pd)[3] = &pa; // pd points to an array of 3 function pointers
Using typedef can reduce the amount of code and make the program easier to understand.
Refer to C++ Primer Plus