与数据类似,函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址。
获取函数的地址很简单:只要使用函数名(后面不跟参数)即可。eg.如果think()是一个函数,则think就是该函数的地址。要将函数作为参数进行传递,必须传递函数名。
process(think); //传递的参数是函数的地址 thought(think()); //传递的参数是函数的返回值声明指向某种类型的指针时,必须指定指针指向的类型。同样,声明指向函数的指针时,也必须指定指针指向的函数的类型。这意味着声明应指定函数的返回类型以及函数的参数列表。即声明应像函数原型那样指出有关函数的信息。
double pam(int); //函数原型 //指针类型声明: double (*pf)(int); //pf指向使用一个int参数并返回double类型的函数将pam替换为了(*pf)。由于pam是函数,因此(*pf)也是函数。则pf就是函数指针。
通常,要声明指向特定类型的函数的指针,可以先编写这种函数的原型,然后用(*pf)替换函数名,这样pf就是这类函数的指针。
括号不能省略:
double (*pf)(int); //pf指向一个返回double的函数 double *pf(int); //pf()是一个函数,返回double指针正确的声明pf后,便可以将相应函数的地址赋给它:
double pam(int); double (*pf)(int); pf = pam; //pam()的参数类型和返回类型必须与pf相同,否则编译器将拒绝赋值使用(*pf)时,只需将它看作函数名即可:
double pam(int); double (*pf)(int); pf = pam; double x = pam(4); double y = (*pf)(5);实际上,C++也允许像使用函数名那样使用pf:
double y = pf(5);程序7.18
#include<iostream> double betsy(int); double pam(int); 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); system("pause"); 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"; }程序7.19
#include <iostream> const double * f1(const double ar[], int n); const double * f2(const double[], int); const double * f3(const double *, int); int main() { using namespace std; double av[3] = { 1112.3, 1542.6, 2227.9 }; //函数指针: const double *(*p1)(const double *, int) = f1; auto p2 = f2; //自动检测类型 //const double *(*p2)(const double *, int) = f2; cout << "Using pointers to functions:\n"; cout << "Address Value\n"; cout << (*p1)(av, 3) << ": " << *(*p1)(av, 3) << endl; cout << p2(av, 3) << ": " << *p2(av, 3) << endl; //pa是一个指针数组 //auto不能用于列表初始化 const double *(*pa[3])(const double *, int) = { f1,f2,f3 }; //auto可以用于单值初始化 auto pb = pa; //const double *(**pb)(const double *, int)=pa; cout << "\nUsing an array of pointers to function:\n"; cout << " Address Value\n"; for (int i = 0; i < 3; i++) cout << pa[i](av, 3) << ": " << *pa[i](av, 3) << endl; cout << "\nUsing a pointer to a pointer to a function:\n"; cout << " Address Value\n"; for (int i = 0; i < 3; i++) cout << pb[i](av, 3) << ": " << *pb[i](av, 3) << endl; //一个指向函数指针数组的指针 cout << "\nUsing a pointer to an array of pointers:\n"; cout << " Address Value\n"; // 一种简单的声明方法: auto pc = &pa; //const double *(*(*pc)[3])(const double *, int) = &pa; cout << (*pc)[0](av, 3) << ": " << *(*pc)[0](av, 3) << endl; //复杂的声明: const double *(*(*pd)[3])(const double *, int) = &pa; //将返回值存储为pdb const double * pdb = (*pd)[1](av, 3); cout << pdb << ": " << *pdb << endl; cout << (*(*pd)[2])(av, 3) << ": " << *(*(*pd)[2])(av, 3) << endl; system("pause"); 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 n) { return ar + 2; }