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

一、函数指针的基础知识

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

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

1.获取函数地址

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

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

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

2.声明函数指针

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

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

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

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

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

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

 double *pf(int);

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

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

 double pam(int);
double (*pf)(int);
pf = pam;

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

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

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

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

 estimate(, pam);

3.使用指针来调用函数

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

 double pam(int);
double (*pf)(int);
pf = pam;
double x = pam(); // 用函数名调用函数
double y = (*pf)(); // 用指针pf调用函数

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

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

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

二、函数指针示例

 /*函数指针示例*/
#include <iostream> using namespace std; //将会被调用的两个函数的声明
double betsy(int);
double pam(int); //estimate()声明
void estimate(int lines, double (*pf)(int)); int main()
{
int code; cout << "请输入代码行数:";
cin >> code;
cout << "Betsy的评估结果:\n";
estimate(code, betsy);
cout << "Pam的评估结果:\n";
estimate(code, pam);
return ;
} 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))
{
cout << lines << "行代码将耗时 ";
cout << (*pf)(lines) << " 小时\n";
}

运行结果:

C++学习笔记之函数指针的更多相关文章

  1. C语言学习笔记之函数指针与函数指针数组

    指针函数:本质是一个函数: 是一个返回指针类型的函数int * sum(){ } 函数指针:本质是一个指针: 是一个指向函数的指针 int (*p)(int,int) = sum; p(5,6); i ...

  2. Matlab学习笔记 figure函数

    Matlab学习笔记 figure函数 matlab中的 figure 命令,能够创建一个用来显示图形输出的一个窗口对象.每一个这样的窗口都有一些属性,例如窗口的尺寸.位置,等等.下面一一介绍它们. ...

  3. iOS学习09C语言函数指针

    本次主要学习和理解函数指针 1.函数指针 void printValue(int number) { printf("number = %d\n", number); } int ...

  4. matlab学习笔记 bsxfun函数

    matlab学习笔记 bsxfun函数 最近总是遇到 bsxfun这个函数,前几次因为无关紧要只是大概看了一下函数体去对比结果,今天再一次遇见了这个函数,想想还是有必要掌握的,遂查了些资料总结如下. ...

  5. Go语言学习笔记九: 指针

    Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...

  6. matlab学习笔记13_1 函数返回值

    一起来学matlab-matlab学习笔记13函数 13_1 函数返回值 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 https://blog.csdn.net/qq_36556 ...

  7. C++学习笔记2_函数.函数指针.函数模板

    1. 内联函数void printAB(int a,int b){ cout<<(a)<<(b)<<endl;}int main(void){ for(int i= ...

  8. swift学习笔记2——函数、闭包

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  9. haskell学习笔记_函数

    一开始学习函数式编程语言就被告知函数式编程语言是一种“定义式”的语言,而不是一种命令式的语言,在学习haskell的函数语法时,此感觉更加强烈,haskell的函数定义倾向于一种类似C++里面的swi ...

随机推荐

  1. socket基础实例(一个服务端对应一个客户端情形)

    服务端处理1个客户端的例子 运行结果: (1) while(accept+if(recv)) 情形 执行服务端进程: [root@localhost single_link]# ./server [s ...

  2. Android服务之Service

    android中服务是运行在后台的东西,级别与activity差不多.既然说service是运行在后台的服务,那么它就是不可见的,没有界面的东西.你可以启动一个服务Service来播放音乐,或者记录你 ...

  3. 编辑时snapping的添加

    原文 编辑时snapping的添加 注意需要在编辑模式下进行snapping的添加(也即先需要使用IEngineEditor进入编辑状态): IMapControl3 mMap = (IMapCont ...

  4. DataTable添加列和行的三种方法

    JRoger 原文 #region 方法一: DataTable tblDatas =new DataTable("Datas"); DataColumn dc =null; dc ...

  5. 点击图片名,让图片在pictureBox中显示 z

    public string filepath; public Form1() { InitializeComponent(); } private void button1_Click(object ...

  6. Oracle V$SESSION详解

    V$SESSION是APPS用户下面对于SYS.V_$SESSION 视图的同义词. 在本视图中,每一个连接到数据库实例中的session都拥有一条记录.包括用户session及后台进程如DBWR,L ...

  7. 链接服务器"(null)"的 OLE DB 访问接口 "Microsoft.Jet.OLEDB.4.0" 返回了消息 "未指定的错误"。[手稿]

    消息 7302,级别 16,状态 1,第 1 行 无法创建链接服务器 "(null)" 的 OLE DB 访问接口 "Microsoft.JET.OLEDB.4.0&qu ...

  8. 全方位掌握 NSIS 的操作

    NSIS 确实是一个不错的安装程序制作软件.新版本2.0a7真正实现了中文支持和支持 WinXP 的安装对话框.不过要用它实现漂亮的安装界面和完美的安装功能就必须好好的写脚本.而 NSIS 的脚本指令 ...

  9. 机器学习&数据挖掘笔记(常见面试之机器学习算法思想简单梳理)

    机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理) 作者:tornadomeet 出处:http://www.cnblogs.com/tornadomeet 前言: 找工作时( ...

  10. 150个JS特效脚本

    收集了其它一些不太方便归类的JS特效,共150个,供君查阅. 1. simplyScroll simplyScroll这个jQuery插件能够让任意一组元素产生滚动动画效果,可以是自动.手动滚动,水平 ...