如何获取函数的地址
函数名本身就是函数的地址。
假设有一个函数think()
,则think
就是该函数的地址。
要将函数作为参数进行传递,必须传递函数名。
1 | process(think); //传递的是函数地址 |
声明函数指针
在声明指向函数的指针时,要声明指针指向的函数的类型,即声明应指定函数的返回值类型和参数列表。
假设有一函数,原型如下:double pam(int);
则正确的指针声明如下:double (*pt)(int)
其中,(*pt)
是函数,pt
是函数指针。
在正确的声明了指针之后,我们就可以将相应的函数的地址赋给它:
pt=pam
使用指针来调用函数
前面指出,(*pt)
是函数,与pam作用相同,因此使用的时候直接将它看作函数名即可。
1 | double pam(int); |
例子
假设我们需要设计一个名为estimate()
的函数,用来计算运行指定行数代码所需要的时间,其中的算法由程序员自己设计决定。
假设程序员设计了两种计算时间的算法,分别为pam()
和betsy()
,其定义如下:
1 | double pam (int lens){ |
则函数estimate()
直接将上面两个函数作为参数,使用如下格式:
1 | estimate(pam,code); |
而函数estimate()
的声明和定义如下:
1 | void estimate(double (*pf)(int),int lens){ |
其中,pf是指向函数的指针,(*pf)就是调用传进来的函数参数。
深入探讨函数指针
假设有下面这些函数原型,他们的参数列表和返回值类型都是相同的。
1 | const double *f1(const double ar[],int n); |
如果要声明一个指针p1,指向上面三个函数之一,则声明如下:
1 | const double *(*p1)(const double *,int)=f1; //声明的同时初始化 |
也就是将函数名f1换成了(*p1)。
使用C++11的自动类型推断功能,代码要简单的多:
1 | auto p2=f2; |
也可以声明一个指针数组,同时初始化:
1 | const double *(*pa[3])(const double *,int)={f1,f2,f3}; |
注意,此时不可以使用auto进行声明,因为auto只能用于单值初始化。
但是声明完pa后,可以用auto声明同样类型的数组:auto pb=pa;
用typedef进行简化
可以使用typedef在程序的开头为函数指针声明一个别名:
1 | typedef const double *(*p_fun)(const double *,int); |
参考资料
C++ Primer Plus 第六版 中文版