函数指针的笔记

       参考资料:《c++ primer plus》,下面是个人的一些笔记和对书上内容的理解

 一.基础知识

1.获取函数的地址:函数名即为函数的地址

      假设think是一个函数,那么,think即为函数的地址,而think(),加上括号,就变成了函数的返回值

      这里有两个例子,

      process(think); 传入的是think的地址,在执行process时会先调用think函数

     而process(think());传入的是think的返回值,在调用完think后,返回值作为参数继续传入process函数中

    

2.声明函数指针:

       与普通的指针 int  *  p 相比  
      函数的指针同样需要指定 指针指向的类型,如上面的 int
        设一个函数原型为  double pam(int);
       那么,函数指针只需要将函数名pam换为指针(*pf)。可以类比普通指针的声明
      int p ; ->int *p ;
     double pam(int); -> double (*pf)(int);
     在调用该函数时,可以将(*pf)当做函数名用,比如 double x =(*pf)(5) ;
     而事实上,直接使用指针也同样可以,如double y = (pf)(5);
     个人倾向于 第一种,这样不容易记混.......
     注意点:
     1.在声明时,*pf一定要括起,
     double (*pf)(int) ;           这里的pf是一个指向函数的指针
     double *pf(int)  ;             这里的pf是一个返回指针的函数    
      
      2.指针的赋值要注意返回类型传入参数类型必须相同
      double (*pf)(int) ;     这里的类型必须一一对应才能赋值
      

3.使用指针调用函数:

     调用时和普通函数名调用一样,将(*pf)指针和函数名(pam)替换就可以
     因此上面的程序就有三种调用方式
     pam(1);使用函数名
     (*pf)(2) ;使用函数指针  
       pf(3);   
   下面是对书上示例部分的理解
    
首先,程序声明了三个函数,它们返回值为指向double类型的指针(见上文,关于将*括起与不括起的区别)
const double *f1(const double ar[],int n);
const double *f2(const double[],int) ;
const double *f3(const double *,int);
要注意这三个声明语句实际上是等价的,在函数原型中,标识符可以省略,这意味f1和f2的等价
double ar[]代表该double类型数组首元素的首地址,因此本质上和double *也是相同的
const double *f1(const double ar[],int n)
{
return ar;
}
另外两个函数就不再写了。
double av[3] = (1111.1,2222.2,3333.4);


再来看两句函数指针的声明
const double *(*p1)(const double *,int) =f1;
auto p2 = f2;
第一句话就是将函数名替换为指针所得,注意不要混淆内外*,外面的*仅代表函数返回的是指针类型
auto为自动类型推断
输出的语句为:
             Address(地址)        Value(值)
cout << (*p1)(av,3) << ": "<<*(*p1)(av,3) << endl;
cout << p2(av,3) << ": "<< *p2(av,3) << endl;
函数返回值是地址,所以直接调用(*p1)得到的是地址值,具体见前文的调用函数的三种方式
  这里还可以使用typedef别名
typedef const *(*p_fun)(const double * ,int );
p_fun p1 = f1 ;
将p_fun作为了一个类型名

下面是一个函数指针的数组
在这之前先列出普通的指针数组的定义,这对学习函数指针的数组也有所帮助
int *p[3];       //声明了一个数组,每个元素都是指向int的指针
int (*p)[3];     //声明了一个指针,指向三维数组
下面是函数指针的数组的定义
const double *(*pa[3])(const double *,int) = {f1,f2,f3};
先忽视外面的*,因为它只代表返回值为指针, 再比照上面的两句就好理解了
这句话代表声明一个数组,它的每个元素都为(返回double *类型的函数)的指针
因此可以将f1,f2,f3作为数组赋值
在64位电脑上,使用sizeof(pa)可以得到结果12  (sizeof(double *)为4)
在使用auto时,注意不能用 auto = {f1,f2,f3}这种语句,auto不能用于初始化列表
正确的,可以使用
auto pb = pa ; 
而用别名表示可以表示为
p_fun pa[3] = {f1,f2,f3};
相比上面的数组定义更容易理解

输出语句如下:
    cout << "\nUsing an array of pointers to function:\n";
    cout << " Address   Value\n";
    for (int i = 0 ; i < 3 ; i++ )
         cout << pa[i](ar,3) << ": " << *pa[i](ar,3) << endl ;
 cout << "\nUsing a pointer to a pointer to a function:\n";  //这样说是因为pb由pa赋值而来,二者都为指针。
    cout << " Address Value\n";
    for (int i = 0 ; i < 3 ; i++)
         cout << pb[i](ar,3) << ": " << *pb[i](ar,3) << endl ;
使用
cout << pa[0](ar,3) << "   "<< f1(ar ,3) << endl;
可以发现二者结果相同,都为地址值。即 pa[i]与f1,f2,f3对应,相当于调用了三个函数,当然(*f1)(ar,3)也与它们的值相同

后面还有指针指向指针数组来调用函数的,个人的理解为取几次地址,就解除几次引用就好
 cout << "\nUsing pointers to an array of function pointers:\n";
    cout << " Address   Value\n";
    auto pc = &pa;
    cout << (*pc)[0](ar,3) << ": " << *(*pc)[0](ar,3) << endl ;

    const double *(*(*pd)[3])(const double * ,int) = &pa ;
    const double *pdb = (*pd)[1](ar,3) ;
    cout << pdb << ": " << *pdb << endl ;

在前文的基础上,加上取地址等来理解就可以


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值