函数指针初学习

目录

声明:本文由笔者在阅读《c++ primer plus》自学第七章函数指针部分后撰写。

函数指针初了解:

函数指针数组

结尾


声明:本文由笔者在阅读《c++ primer plus》自学第七章函数指针部分后撰写。

函数指针初了解:

显然,被定义的函数在编程中与被定义的变量类似,也有其存储的相应地址,而指向存储一个函数的地址的指针自然也就是函数指针了,并且一个函数的地址可以由函数名来表示。通过函数指针也可以实现函数的调用,且很多时候能够带来好处。

#include <iostream>
using namespace std;
double f1(double a,double b){
    return a+b;
}//函数原型及函数定义
int main(){
    double (*p1)(double a,double b);
    p1=f1;//f1为函数名,函数名本身就可以表示一个函数的地址
    cout<<(*p1)(12.2,3.6)<<endl;//函数指针的调用方法之一
    return 0;
}

以上代码便是一种最简单的定义函数指针的方法,从中可以看出函数的地址可以用函数名本身来表示,而我们需要做的便是定义好一个符合该函数类型的指针p1,就可以通过p1=f1来实现让p1指向对应的函数f1了。

而学习过程中很容易便发现了,每次编写一大串的函数类型着实很麻烦,而学习了相关内容后就可以发现,可以通过自动类型推断auto或者typedef来简化过程,下面放一段用auto的代码:

#include <iostream>
using namespace std;
const double* f1(const double* ,int );
int main(){
    double s1[10]={1,2,3,4};
    auto p1=f1;
    for(int i=0;i<5;i++){
        cout<<(*p1)(s1,i)<<'\t'<<':'<<'\t'<<*(*p1)(s1,i)<<endl;
    }
    cout<<"另一种编程方法,输出结果相同:"<<endl;
    for(int i=0;i<5;i++){
        cout<<p1(s1,i)<<'\t'<<':'<<'\t'<<*p1(s1,i)<<endl;//  \t为制表符
    }
    //应当注意:这种等价只针对于函数指针有效!
    return 0;
}
const double* f1(const double* p1,int a){
    return p1+a;//返回的是指针
}

这里采用的是先定义函数原型,在main函数之后给出完整函数定义的方式。可以看到通过auto p1 = f1,编译器自动识别了f1为函数名也即函数地址,故将p1定义为指针,指向函数f1,实现了快速且方便的定义。

同时这里还展示出了函数指针的两种调用方式,一种是符合逻辑上的先用(*p1)来找到对应函数,再调用,也即"(*p1)(此处放参数)"的方法,另一种则是直接把p1当成函数f1来使用,而不必再额外添加*号。

函数指针数组

类比其他的指针,函数指针显然也可以采用数组来存储,也就是所谓的函数指针数组,这里的函数指针数组基本可以完全类比其他普通类型的指针数组。

再看写的第二个程序:

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
// 函数指针数组
const double *f1(const double *, int);
const double *f2(const double *, int);
const double *f3(const double *, int);
int main()
{
    cout<<"New Start\n";
    double ar[10] = {11.5, 223.3, 423.32, 35.234, 87.34,137.842,654.134,13.445,23.75};
    const double *(*pa[10])(const double *, int);
    pa[0] = f1;
    pa[1] = f2;
    pa[2] = f3;
    for(int i=0;i<3;i++){
        printf("第%d个函数对应的输出:",i+1);
        for(int j=0;j<5;j++){
            cout<<(*pa[i])(ar,j)<<'\t'<<*(*pa[i])(ar,j)<<endl;//事实上,很多时候()时候可以省略的,写成如同**pa的形式即可。
        }
    }
    //下面采用auto来简化编写程序的过程。
    auto pb=pa;//pb指向pa数组,pb+i可理解为pa[i];
    for(int i=0;i<3;i++){
         printf("第%d个函数对应的输出:",i+1);
        for(int j=0;j<5;j++){
            cout<<(*(pb[i]))(ar,j)<<'\t'<<*(*(pb[i]))(ar,j)<<endl;//事实上,很多时候()时候可以省略的,写成如同**pa的形式即可。
        }//pb[i]<==>pb+i;
    }
    return 0;
}
const double *f1(const double *ar, int r)
{
    return ar + r;
}
const double *f2(const double *ar, int r)
{
    return ar + r+1;
}
const double *f3(const double *ar, int r)
{
    return ar + r + 2;
}

//这里图省事就直接开了个大小为10的数组,不过自然也懒得去写10个函数把这个数组填满,强迫症请见谅……

pa数组也就是存储函数指针的数组。自然的,pa[i]也就表示pa+i。这些都是与其他类型的指针相同的。

而定义函数指针类型的数组时,同样的也需要交代清楚类型,也即这一行

const double *(*pa[10])(const double *, int);

前面的const double *表示了函数的返回类型,后面的(const double *,int)则表示了函数所需的参数,这些一起描述了函数的类型。 而中间的*pa[10]则表示该类型的指针数组。就如同int表示类型时,定义方法为int *pa[10]。

同样的也可以采用auto简化定义方式,见上面的代码中pb有关实现。

提到了类型的概念,就比较方便理解typedef在这里的作用了,见下面采用typedef的代码:(在第二个程序的基础上略加修改得到)

//本篇采用typedef来简化类型定义的编辑
#include <iostream>
using namespace std;
typedef const double* (*p_fun/*这里*p_fun表示p_fun是指针类型*/) (const double *,int);//函数指针类型定义,即创建了一种p_fun类型,为函数指针类型
const double* f1(const double* ,int );
int main(){
    double s1[10]={1,2,3,4};
    p_fun p1=f1;
    for(int i=0;i<5;i++){
        cout<<(*p1)(s1,i)<<'\t'<<':'<<'\t'<<*(*p1)(s1,i)<<endl;
    }
    cout<<"另一种编程方法,输出结果相同:"<<endl;
    for(int i=0;i<5;i++){
        cout<<p1(s1,i)<<'\t'<<':'<<'\t'<<*p1(s1,i)<<endl;//  \t为制表符
    }
    //应当注意:这种等价只针对于函数指针有效!
    return 0;
}
const double* f1(const double* p1,int a){
    return p1+a;//返回的是指针
}

结尾

以上便是我在浅略学习这一部分的code内容了,剩下的还有一些小的部分没有具体敲出相应代码来实现,例如指针的指针等,函数名的地址等,总之它们大体都类似于其他类型的指针与地址的处理方式,不再一一展开。

本文属于笔者的自学记录与总结,如有不足欢迎评论指点。

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值