函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址。
函数指针的基础知识
假设设计一个名为estimate()的函数,用来估算编写指定行数的代码所需的时间,并且希望不同程序员都可以使用该函数,对于所有用户来讲,estimate()中的一部分代码是相同的,但该函数允许每个程序员提供自己的算法来估算时间。为了 实现这个目的,采用的机制是,将程序员要使用的算法函数的地址传递给estimate()。为此,必须完成以下工作:
- 获取算法函数的地址
- 调用一个函数指针
- 使用函数指针来调用函数
1.获取函数地址 获取函数地址,只需使用函数名即可。比如,有一个think()函数,获取此函数的地址,只需进行如下调用:
process(think);
要分清楚是函数地址和函数返回值,如下调用利用率函数的返回值:
process(think());
2.声明函数指针声明某个类型的数据指针时,必须指明指针指向的类型,同样,声明函数指针时也必须指明指针指向的函数类型,这意味着必须指明函数的返回值类型和函数参数列表。假如,有这样一个函数,函数原型是double process(int),则正确的函数指针形式如下:
double (*pt)(int);
在这里 ,用 *pt 替换了process,通常,要声明指定类型的函数指针,可以先编写该函数的原型,然后再用 ( *pt )替换函数名,这样pt就是指向函数的指针。
3.使用指针来调用函数使用指针来调用被指向的函数,由于( *pt)与函数名一致,因此使用( *pt)时,将它看做函数名。代码如下:
double process(int);
double (*pt)(int);
double x=process(4); //valid
double y=(*pt)(4); //valid
//实际上,c++也允许像使用函数名那样,使用pt
double z=pt(4); //also valid
函数指针示例
还是那个算法时间估计程序,代码如下:
#include <iostream>
using namespace std;
double f1(int);//算法程序1
double f2(int);//算法程序2
void estimate(int line,double (*pt)(int));//算法公用程序
int main()
{
int code;
cout<<"How many lines of code do you need ?"<<endl;
cin>>code;
cout<<"Here is f1's estimate :\n";
estimate(code,f1);
cout<<"Here is f2's estimate :\n";
estimate(code,f2);
return 0;
};
double f1(int lns)
{
return(1*lns);
}
double f2(int lns)
{
return(2*lns);
}
void estimate(int line,double (*pt)(int))
{
cout<<line<<" line will take : "<<pt(line)<<" hours \n";
}
输出结果:
深入探讨函数指针
1.创建函数指针数组
形式如下:
double (*pa[3])(int);
pa是一个包含三个元素的数组,首先需要使用 pa[3] 来声明;该声明的其他部分指出了数组元素的类型是什么,运算符 [ ] 比 * 的优先级高, 因此 *pa[3] 表明pa是一个包含三个指针的数组。上述声明的其他部分指出了每个指针指向的是什么:其指向的是函数返回值为double,函数参数列表为int这样的函数。
2.通过调用函数指针数组来调用函数
double x=pa[0](3); //valid
double x=(*pa[0])(3); //valid
3.创建指向整个函数指针数组的指针
由于数组名pa是指向函数指针数组的指针,因此,指向函数指针数组的指针将是这样的指针,即它指向数组指针的指针。初始化形式:auto pc=&pa;
或者是如下形式:
double *((*pd)[3])(int)=&pa;