函数指针是什么?
大家都知道,指针的本质,无非就是一个值,用来指向一个内存的地址。
在一个可执行程序中,函数本身也被加载到内存中,并且也有一个具体的地址。
因此,同样可以用指针来指向一个函数,这种指向函数入口地址的指针,就是函数指针。
为什么要使用函数指针?
上面说了,函数指针是一种指向函数的指针,它可以存储函数的地址,并在需要时调用该函数。
函数指针在C++中有很多用途,以下是一些常见的应用场景:
- 回调函数:函数指针最常用的用途之一是实现回调机制。在回调机制中,一个函数接受另一个函数作为参数,并在某个事件或条件满足时调用它。这在事件驱动编程和异步编程中非常有用。
- 函数数组:可以创建一个函数指针数组,这样就可以根据索引来调用不同的函数。这在实现基于状态机的程序时非常有用,可以根据状态选择不同的行为。
- 多态:函数指针可以用来实现运行时多态。通过将函数指针指向派生类的成员函数,可以在基类指针上调用派生类中重写的方法。
- 动态绑定:函数指针可以用来实现动态绑定,即在运行时决定调用哪个函数。这在需要根据不同情况调用不同函数时非常有用。
- 接口实现:在没有虚函数的类中,函数指针可以用来模拟接口的行为,允许不同的类通过不同的实现来响应相同的操作。
- 优化代码:在某些情况下,使用函数指针可以提高代码的执行效率,尤其是在需要频繁调用函数的情况下,通过函数指针直接调用可以减少函数查找的时间。
- 信号和槽机制:在Qt等框架中,函数指针用于实现信号和槽机制,允许对象之间的松耦合通信。
- 函数工厂:函数指针可以用来创建函数工厂,即根据输入参数动态创建并返回不同类型的函数。
- 装饰器模式:在设计模式中,函数指针可以用来实现装饰器模式,允许在不修改原有函数的情况下增加额外的功能。
等等。
函数指针是C++中一个强大的特性,它提供了一种灵活的方式来引用和调用函数,使得代码更加模块化和可重用。
先来看一个Hello World程序
int main(int argc,char* argv[])
{printf("Hello World!\n");return 0;
}
采用函数调用的形式来实现
这是一种常规的使用方式。
void Invoke(char* s);
int main(int argc,char* argv[])
{Invoke("Hello World!\n");return 0;
}void Invoke(char* s)
{printf(s);
}
用函数指针的方式来实现
如下:
void Invoke(char* s);int main()
{void (*fp)(char* s); //声明一个函数指针(fp) fp=Invoke; //将Invoke函数的入口地址赋值给fpfp("Hello World!\n"); //函数指针fp实现函数调用return 0;
}void Invoke(char* s)
{printf(s);
}
说明
函数指针函数的声明之间唯一区别就是,用指针名(*fp)
代替了函数名Invoke,这样这声明了一个函数指针,然后进行赋值语句:
fp=Invoke
就可以进行函数指针的调用了。声明函数指针时,只要函数返回值类型、参数个数、参数类型等保持一致,就可以声明一个函数指针了。
注意,函数指针必须用括号括起来,如下:
void (*fp)(char* s)
函数指针数组
来个例子:
#include <iostream>
#include <string>
using namespace std;typedef void (*FP)(char* s);
void f1(char* s){cout<<s;}
void f2(char* s){cout<<s;}
void f3(char* s){cout<<s;}int main(int argc,char* argv[])
{void* a[]={f1,f2,f3}; //定义了指针数组,这里a是一个普通指针a[0]("Hello World!\n"); //编译错误,指针数组不能用下标的方式来调用函数FP f[]={f1,f2,f3}; //定义一个函数指针的数组,这里的f是一个函数指针f[0]("Hello World!\n"); //正确,函数指针的数组进行下标操作可以进行函数的间接调用return 0;
}
实际中,为了方便,通常用宏定义的方式来声明函数指针,实现程序如下:
typedef void (*FP)(char* s);
void Invoke(char* s);int main(int argc,char* argv[])
{FP fp; //通常是用宏FP来声明一个函数指针fpfp=Invoke;fp("Hello World!\n");return 0;
}void Invoke(char* s)
{printf(s);
}
后记
c++因为可以直接操作指针,很多时候,可以比java、python、go等高级语言有更多灵活性,所以,在系统层面,还是有其不可替代性的。
关于函数指针的具体应用,慢慢补充。