函数指针详解

来源:互联网 发布:云尚数据 编辑:程序博客网 时间:2024/06/06 12:45

选自《C++ Primer Plus(第六版)》

  与数据项类似,函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址。

  1.函数指针的基础知识

  首先通过一个例子来阐述这一过程。假设要设计一个名为estimate()的函数,估算编写指定行数的代码所需的时间,并且希望不同的程序员都将使用该函数。对于所有的用户来说,estimate()中一部分代码都是相同的,但该函数允许每个程序员提供自己的算法来估算时间。为了实现这种目标,采用的机制是,将程序员要使用的算法函数的地址传递给estimate()。为此,必须能够完成下面的工作:

  • 获取一个函数的地址;
  • 声明一个函数指针;
  • 使用函数指针来调用函数

  1.获取函数的地址
  获取函数的地址很简单:只要使用函数名(后面不跟参数)即可。注意传递的是函数地址还是函数的返回值,假如think()是一个函数,那么有:

process(think);  //passes address of think() to processthought(think()); //passes return value of think() to thought

  2.声明函数的指针
  声明函数指针时,必须要指定函数的返回类型以及函数的特征标(参数列表)。例如:
  double pam(int); //prototype
  则正确的指针类型声明如下:

double (*pf)(int); //pf points to function that takes one int                     //argument and that returns type doublepf=pam;   //pf now points to the pam() function

  这时pf就是函数指针,(*pf)就是函数。注意pam()的特征标和返回类型必须与pf相同。
  ps:区分函数指针和返回指针的函数:
  因为括号的优先级比*运算符高,因此*pf(int)意味着pf()是一个返回指针的函数,而(*pf)(int)意味着pf是一个指向函数的指针。

double (*pf)(int);  //pf points to a function that returns doubledouble *pf(int);  //pf() a function that returns a pointer-to-double

  3.使用函数指针来调用函数
  这步比较简单,如下:

double pam(int); double (*pf)(int);pf=pam;  //pf now points to the pam() function double x=pam(4); //call pam() using the function namedouble y=(*pf)(5); //call pam() using the pointer pf

  实际上,C++也允许像使用函数名那样使用of:
  double y=pf(5); //also call pam() using the pointer pf
  第一种格式虽然不太好看,但它给出了强有力的提示——代码正在使用函数指针。

  2.函数指针示例

  程序清单:

#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);}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";}

  简要解释:该程序两次调用estimate()函数,一次传递betsy()函数的地址,另一次传递pam()函数的地址。
  运行结果:
  这里写图片描述

  3.深入探讨函数指针

const double* f1(const double ar[],int n);const double* f2(const double [],int);const double* f3(const double *,int);//这些函数实际上是相同的const double* (*p1)(const double *,int);//可在声明的同时进行初始化:const double* (*p1)(const double *,int)=f1;//使用C++11的自动类型推断功能,代码要简单的多auto p2=f2;  //C++11 automatic type deductioncout<<(*p1)(av,3)<<": "<<*(*p1)(av,3)<<endl;cout<<p2(av,3)<<": "<<*p2(av,3)<<endl;

  根据前面讲的,(*p1)(av,3)和p2(av,3)都调用指向的函数(这里为函数f1()和f2()),并将av和3作为参数。因此,显示的是这两个函数的返回值。返回值的类型为const double*(即double值的地址),因此在每条cout语句中,前半部分显示的是一个double值的地址;为了查看存储在这些地址处的实际值,需要将运算符*应用于这些地址,如表达式*(*p1)(av,3)和*p2(av,3)。
  鉴于需要使用三个函数,如果有一个函数指针数组将很方便。这样,将可使用for循环通过指针一次调用每个函数。声明方法如下(包括初始化):
  const double* (*pa[3])(const double *,int)={f1,f2,f3};
  ps:因为运算符[]的优先级高于*,所以这里pa是一个包含三个指针的数组,其中每个指针都指向这样的函数,即将const double*和int作为参数,并返回一个const double *
  这里不能用auto。自动类型推断只能用于单值初始化,而不能用于初始化列表。

//调用函数的两种写法const double * px=pa[0](av,3);const double * py=(*pa[1])(av,3);//获得指向的double值,可使用运算符*double x=*pa[0](av,3);double y=*(*pa[1])(av,3);

  区分指向数组的指针和函数指针数组:

*pd[3]; //an array of 3 pointers(*pd)[3]; // a pointer to an array of 3 elements

  这样就会使指针的使用显得非常恐怖,关于的指针的特性还有待进一步的了解。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 物流把东西损坏怎么办 物流公司损坏货物怎么办? 汽油泵不上水怎么办 电脑启动卡住了怎么办 电脑不能截屏怎么办 手机解不了锁怎么办 macbook关不了机怎么办 电脑用不了网络怎么办 硝酸银滴在皮肤怎么办 手镯买大了怎么办 汪里有野花生草怎么办 喝普洱茶牙齿发黄怎么办 误吃黄曲霉素怎么办 考完芒果干很酸怎么办 面团加水多了怎么办 榨花生油有渣怎么办 花生秧牛不吃怎么办 花生吃多拉肚子怎么办 吃生花生腹泻怎么办 花生瓜子皮了怎么办 牛轧糖做的太硬怎么办 芝麻糖软了怎么办 芝麻糖变软了怎么办 12123登录不进去怎么办 小车排气管漏了怎么办? 货车排气管堵了怎么办 汽车排气管声音大怎么办 汽车排气管堵了怎么办 空调电磁阀坏了怎么办 3dmax文件太大怎么办 肾脏有小结石怎么办 摩托车机油烧干怎么办 摩托车机油干了怎么办 轴承取不下来怎么办 摩托车前刹车抱死怎么办 风扇轴承坏了怎么办 尼龙料产品缩水怎么办 八六盒螺丝掉了怎么办 政府办事遇推诿怎么办 民心网投诉不管怎么办 齐星破产工人怎么办