函数指针
函数指针->指向函数的指针 c++ pp page199
声明方法:
如果一个计算简单加法的函数原型为:
int sum(int ,int);
那么指向该函数的指针 p 应该这样声明:
int (*p)(int,int); p = sum;//p point to sum
可以看到,获取函数的地址,只要使用函数名(后面不跟参数)即可。
使用该指针的方法
cout<<sum(1,2); cout<<(*p)(1,2); cout<<p(1,2);//note
需要注意的是,函数指针 p 指向函数sum,那么之前所说的,使用sum函数应该用 (*p)(1,2),但是,c++也允许直接将p用作函数名 p(1,2)。
将一个函数a作为另一个函数b的参数时,另一个函数b的形参中应该写上一个指向函数的指针,并将函数a的地址传递给该形参。此外,将上面的 sum() 函数作为另一个函数sum1()函数的参数时,若要将sum(1,2)作为形参,不可以将sum()的参数1和2与sum()函数一起放在一个形参中,而应该将sum()的两个实参1和2,分别作为sum1()的两个形参,如下代码所示:
#include <iostream> using namespace std; int sum(int,int); int sum1(int,int,int,int (*p)(int,int)); int main() { cout<<sum1(3,1,2,sum)<<endl;//计算3+sum(1,2) return 0; } int sum(int a,int b) { return a+b; } int sum1(int a,int b,int c,int (*p)(int ,int )) { return a + (*p)(b,c); }
关于函数指针数组和指向函数指针数组的指针,参考
https://blog.csdn.net/cherishinging/article/details/72229626、
该篇博客中讲清楚了如何使用[]和*的优先级关系来判定变量p是和[]结合作为数组名还是和*结合作为指针名;应仔细揣摩。
在该篇博客中,最后一部分讲指向函数指针数组的指针时,例子:
#include <stdio.h> #include <string.h> char* fun1(char* p) { printf("%s\n",p); return p; } char* fun2(char* p) { printf("%s\n",p); return p; } char* fun3(char* p) { printf("%s\n",p); return p; } int main() { char* (*a[3])(char* p); char* (*(*pf)[3])(char* p); pf = &a; a[0]= fun1; a[1]= &fun2; a[2]= &fun3; pf[0][0]("fun1"); pf[0][1]("fun2"); pf[0][2]("fun3"); return 0; }
a是一个函数指针数组的数组名,应该是一个指针(地址,即数组第一个元素的地址)pf是指向函数指针数组的指针名,赋值为什么用pf = &a;为什么 pf = a;不对?
在c++ pp page90 中提到过,数组名是数组第一个元素的地址,即上面的例子中, a 是函数指针数组第一个元素的地址(指针),而 &a 是整个函数指针数组的指针。
因为pf是指向整个函数指针数组的指针,而不是指向函数指针数组第一个元素的指针,指向函数指数组第一个元素的指针pq应该这样定义:
char* (**pq)*(char* p); pq = a;
再举一个例子:
#include <iostream> using namespace std; const double * f1(const double ar[],int n); const double * f2(const double [],int); const double * f3(const double *,int); int main() { const double ar[3] = {1,2,3}; const double * (*p[3])(const double *,int ); p[1] = f1; p[2] = f2; p[3] = f3; const double * (**pp)(const double *,int);//指向函数指针数组p的第一个元素的指针pp pp = p; const double * (*(*ppp)[3])(const double * ,int);//指向整个函数指针数组p的指针ppp ppp = &p; (*pp)(ar,1);//pp是指向函数指针数组p的第一个元素的指针,则(*pp)就是函数指针数组的第一个元素 (*(*pp))(ar,1);//对于个函数指针p的调用可以直接用p(1,2)或(*p)(1,2) (*ppp)[0](ar,1);//ppp是指向函数指针数组的指针,则(*ppp)就是该函数指针数组,(*ppp)[0]就是该函数指针数组的第一个元素 (*((*ppp)[0]))(ar,1); return 0; } const double * f1(const double ar[],int n) { return ar; } const double * f2(const double ar[],int n) { return ar; } const double * f3(const double ar[],int n) { return ar; }
那么,如果pf和ppp都是指向整个数组的指针,应该如何使用呢?
既然pf和ppp都指向整个数组,那么(*pf)和(*ppp)就是整个数组,而(*pf)[0]和(*ppp)[0]就是整个数组的第一个元素。
最后一个例子:
int main() { int a = 1; int b = 2; int c = 3; int* p[3] = {&a,&b,&c}; int* *pp = p; int* (*ppp)[3] = &p; cout<<*((*ppp)[0])<<endl; return 0; }
上例中,p是一个整形指针数组的数组名,即p是该数组中第一个元素的地址(指针);而pp是指向该数组第一个元素的指针;ppp是指向整个整形指针数组的指针;
因此,(*ppp)就是整个整形指针数组,(*ppp)[0]就是整个整形指针数组的第一个元素,即&a,因此*((*ppp)[0])就是a;程序输出1;
实际上,当类型过于复杂时,可以使用auto来声明;
详解见c++ pp page202-203;