函数指针

函数指针->指向函数的指针 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;

 

posted @ 2022-02-28 20:53  SanFranciscoo  阅读(106)  评论(0编辑  收藏  举报