zoukankan      html  css  js  c++  java
  • C++学习笔记之函数指针

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

    一、函数指针的基础知识

    假设要设计一个名为estimate()的函数,估算编写指定行数代码所需时间,并且希望不同的程序员都使用该函数,并且该函数允许每个程序员提供自己的算法来估计时间。为实现这种目标,采用的机制是,将程序员要使用的算法函数地址传给estimate(),必须完成以下工作:

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

    1.获取函数地址

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

    一定要注意区分传递的是函数的地址还是函数的返回值:

    1 process(think);    //传递函数think()的地址给process()
    2 thought(think()); //传递函数think()的返回值给though()

    2.声明函数指针

    声明应指定指针所指向的函数的返回类型以及函数的特征标(参数列表),假设Pam编写了一个估算时间的函数,其原型如下:

    1 double pam(int);    // 函数声明

    则正确的指针类型声明如下:

    1 double (*pf) (int); 
    2 // pf指向一个输入一个int参数,返回一个double值得函数

    可以看出,就是将函数声明中的函数名替换为*pf, 于是pf就成为指向函数的指针,由指针的基本知识可以知道,(*pf)也是函数。

    必须在声明中用括号将*pf括起,否则如下:

    1 double *pf(int);

    这相当于声明了一个函数pf,它的返回值是一个指向double的指针,与我们想要声明的函数指针完全不是一码事。

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

    1 double pam(int);
    2 double (*pf)(int);
    3 pf = pam;

    现在指针pf就指向函数pam()了。再次强调pam()的特征标和返回类型必须与pf相同。

    假设现在要将编写的代码行数和估算算法(如pam()函数)的地址传递给estimate(),原型如下:

    1 void estimate(int lines, double (*pf)(int));

    要让estimate()使用pam()函数,需要将pam()的地址传给它:

    1 estimate(50, pam);

    3.使用指针来调用函数

    上面讲过,(*pf)扮演的角色与函数名相同,因此使用(*pf)时,只需将它看作函数名即可:

    1 double pam(int);
    2 double (*pf)(int);
    3 pf = pam;
    4 double x = pam(4);   // 用函数名调用函数
    5 double y = (*pf)(5);  // 用指针pf调用函数

    但是,C++也允许像使用函数名那样使用pf:

    double y = pf(5);  //与double y = (*pf)(5)效果一样

    为何pf与(*pf)等价呢?因为存在两种看法,一种学派认为,由于pf是函数指针,而*pf是函数,因此应将(*pf)()用作函数调用;而另一种学派认为,由于函数名是指向该函数的指针,指向函数指针的行为应与函数名相似,因此应将pf()用作函数调用。看上去都是合理的说法,因此C++进行了折衷--两种方法都正确,虽然在逻辑上相互冲突。

    二、函数指针示例

     1 /*函数指针示例*/
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 //将会被调用的两个函数的声明
     7 double betsy(int);
     8 double pam(int);
     9 
    10 //estimate()声明
    11 void estimate(int lines, double (*pf)(int));
    12 
    13 int main()
    14 {
    15     int code;
    16 
    17     cout << "请输入代码行数:";
    18     cin >> code;
    19     cout << "Betsy的评估结果:
    ";
    20     estimate(code, betsy);
    21     cout << "Pam的评估结果:
    ";
    22     estimate(code, pam);
    23     return 0;
    24 }
    25 
    26 double betsy(int lns)
    27 {
    28     return 0.05 * lns;
    29 }
    30 
    31 double pam(int lns)
    32 {
    33     return 0.03 * lns + 0.0004 * lns * lns;
    34 }
    35 
    36 void estimate(int lines, double (*pf)(int))
    37 {
    38     cout << lines << "行代码将耗时 ";
    39     cout << (*pf)(lines) << " 小时
    ";
    40 }

    运行结果:

  • 相关阅读:
    Git中使用.gitignore忽略文件的推送
    git stash详解
    Git撤销&回滚操作(git reset 和 get revert)
    git rebase和git merge的区别
    git撤销已经push到远程仓库上的代码
    Git Merge
    git cherry-pick 教程
    Failed to start LSB: Bring up/down错误解决方法
    linux centos7安装部署gitlab服务器
    CentOs7 HP找回root密码
  • 原文地址:https://www.cnblogs.com/90zeng/p/Cpp_function_pointer.html
Copyright © 2011-2022 走看看