【C++】学习笔记三十八——函数指针

函数指针

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


函数指针的基础知识

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

1.获取函数的地址

  获取函数的地址很简单:只要使用函数名(后面不跟参数)即可。eg.如果think()是一个函数,则think就是该函数的地址。要将函数作为参数进行传递,必须传递函数名。

process(think);     //传递的参数是函数的地址
thought(think());   //传递的参数是函数的返回值

2.声明函数指针

  声明指向某种类型的指针时,必须指定指针指向的类型。同样,声明指向函数的指针时,也必须指定指针指向的函数的类型。这意味着声明应指定函数的返回类型以及函数的参数列表。即声明应像函数原型那样指出有关函数的信息。

double pam(int);    //函数原型
//指针类型声明:
double (*pf)(int);    //pf指向使用一个int参数并返回double类型的函数

将pam替换为了(*pf)。由于pam是函数,因此(*pf)也是函数。则pf就是函数指针。

通常,要声明指向特定类型的函数的指针,可以先编写这种函数的原型,然后用(*pf)替换函数名,这样pf就是这类函数的指针。

括号不能省略:

double (*pf)(int);  //pf指向一个返回double的函数
double *pf(int);    //pf()是一个函数,返回double指针

正确的声明pf后,便可以将相应函数的地址赋给它:

double pam(int);
double (*pf)(int);
pf = pam; //pam()的参数类型和返回类型必须与pf相同,否则编译器将拒绝赋值

3.使用指针来调用函数

使用(*pf)时,只需将它看作函数名即可:

double pam(int);
double (*pf)(int);
pf = pam;
double x = pam(4);
double y = (*pf)(5);

实际上,C++也允许像使用函数名那样使用pf:

double y = pf(5);

函数指针示例

程序7.18

#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);
    system("pause");
    return 0;
}

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

这里写图片描述


深入探讨函数指针

程序7.19

#include <iostream>

const double * f1(const double ar[], int n);
const double * f2(const double[], int);
const double * f3(const double *, int);

int main()
{
    using namespace std;
    double av[3] = { 1112.3, 1542.6, 2227.9 };

    //函数指针:
    const double *(*p1)(const double *, int) = f1;
    auto p2 = f2;               //自动检测类型
    //const double *(*p2)(const double *, int) = f2;
    cout << "Using pointers to functions:\n";
    cout << "Address Value\n";
    cout << (*p1)(av, 3) << ": " << *(*p1)(av, 3) << endl;
    cout << p2(av, 3) << ": " << *p2(av, 3) << endl;

    //pa是一个指针数组
    //auto不能用于列表初始化
    const double *(*pa[3])(const double *, int) = { f1,f2,f3 };
    //auto可以用于单值初始化
    auto pb = pa;
    //const double *(**pb)(const double *, int)=pa;
    cout << "\nUsing an array of pointers to function:\n";
    cout << " Address  Value\n";
    for (int i = 0; i < 3; i++)
        cout << pa[i](av, 3) << ": " << *pa[i](av, 3) << endl;
    cout << "\nUsing a pointer to a pointer to a function:\n";
    cout << " Address  Value\n";
    for (int i = 0; i < 3; i++)
        cout << pb[i](av, 3) << ": " << *pb[i](av, 3) << endl;

    //一个指向函数指针数组的指针
    cout << "\nUsing a pointer to an array of pointers:\n";
    cout << " Address  Value\n";
    // 一种简单的声明方法:
    auto pc = &pa;
    //const double *(*(*pc)[3])(const double *, int) = &pa;
    cout << (*pc)[0](av, 3) << ": " << *(*pc)[0](av, 3) << endl;
    //复杂的声明:
    const double *(*(*pd)[3])(const double *, int) = &pa;

    //将返回值存储为pdb
    const double * pdb = (*pd)[1](av, 3);
    cout << pdb << ": " << *pdb << endl;
    cout << (*(*pd)[2])(av, 3) << ": " << *(*(*pd)[2])(av, 3) << endl;
    system("pause");
    return 0;
}

const double * f1(const double * ar, int n)
{
    return ar;
}

const double * f2(const double ar[], int n)
{
    return ar + 1;
}

const double * f3(const double ar[], int n)
{
    return ar + 2;
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值