什么是函数指针
指针作为C/C++最重要的概念之一,也是最难理解的概念之一。其作用可以粗略地用这个例子解释:就像我们可以通过门牌号找到搬家后朋友的住址一样,我们可以通过指针去寻址和访问内存中指定地址的数据。不过在这里我们就不深入了,仅对函数指针作说明。
1. 什么是函数指针
不止int
、float
之类的数据类型可以用指针进行操作,C/C++中,函数也可以使用指针进行操作。
如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。
其声明如下:
|
|
2. 为什么有函数指针
首先看一段代码:
|
|
其执行结果为:
|
|
这里我定义了一个Animal
类,有一个Eat
方法;然后定义了三种不同动物的进食函数
;Eat
方法通过函数指针调用了不同的进食函数。食物是草
时,就调用羊的进食函数;食物是羊
时,调用狼的进食函数;如此类推,我们可以拓展更多动物,甚至将动物按草食、肉食、杂食三个类进行封装。而我们只用了一个类,一个方法,这就是函数指针的魅力。
如果没有函数指针,对于这种确定返回值类型和参数类型,但是功能各有不同的函数。面对千变万化的需求,你需要为每种情况继承一个子类;但是有了函数指针,你只要在方法里声明一个函数指针作为一个接口
去调用写好的不同函数,只用一个类便完成了这个任务,这就叫抽象
和封装
。函数指针把基于流程的函数变成了一个可以作为参数调用的变量,从而让代码变得更加优雅。
函数指针还有一个典型的应用就是回调函数
,譬如上面我对于不同的食物,使用了不同的进食函数。羊、狼、人都饿了,但是羊不爱吃青椒肉丝,人也不喜欢吃狼。它们拜托你寻找食物,找到了叫回(callback
)它们。你找到了草
,叫回了羊
去执行进食函数;现在你找到了羊
,那么就该叫狼
回来去干点什么了……
此时这些进食函数就叫回调函数
,而你就是Animal
类的Eat
方法。它们拜托你找食物就叫登记回调函数,你找到了食物叫做触发了回调关联的事件,你叫它们回来进食叫做调用回调函数,它们前来进食就叫响应回调事件。
3. 函数指针怎么用
还是参见代码:
|
|
其执行结果为:
|
|
可以看到其使用方法和函数没什么区别,但这并不意味着函数指针和函数名等价!函数名只是个符号,在编译时会被替换为函数的入口地址,在执行时固定不变;而函数指针需要额外占用 字长 大小的内存空间来保存函数入口地址,同时其值在程序运行中可变。