函数指针
函数具有可赋值给指针的物理内存地址,一个函数的函数名就是一个指针,它指向函数的代码。一个函数的地址是该函数的进入点,也是调用函数的地址。
1 定义
函数指针指的是指向函数的指针,函数指针指向某种特定的类型。而函数类型由它的返回类型和形参类型共同决定,与函数名无关。例如:
int add(int, int); //定义了一个函数原型
int (*pf)(int, int); //声明一个函数指针,未初始化
//可以使用typedef类型别名来简化
typedef int (*PF)(int, int);
PF pf2; //声明一个函数指针
我们声明了一个函数,该函数的函数类型是int (int, int)。
同时还声明了一个指向函数的指针 pf,该函数的参数是两个 int 类型,返回值是int类型。因此,函数指针 pf 可以指向一个类型为 *int (int, int)*的函数。
2 初始化
pf = add; //pf指向名add的函数
pf = &add; //等价的赋值语句,取地址符是可选的,
3 函数指针的使用
函数的调用可以通过函数名,也可以通过指向函数的指针来调用。函数指针还允许将函数作为变元传递给其他函数。例如:
3.1 普通调用
int sum1 = pf(3, 4); //调用add函数
int sum2 = (*pf)(3, 4); //等价的调用
int sum3 = add(3, 4); //等价的调用
3.2 函数指针做形参
//第二个形参为函数类型,会自动转换为指向此类函数的指针
Void fuc1(int a, int b, int pf(int,int));
//等价的声明,显式的将形参定义为指向函数的指针
Void func2(int a, int b, int (*pf)(int,int));
Void func3(int a, int b, PF);
形参中有函数指针的函数调用,例如:
pf = add;
pf2 = add;
func1(3, 4, add); //add自动转化为指针
func2(3, 4, pf);
func3(3, 4, pf2);
4 重载函数的指针
如果定义了指向重载函数的指针
int add(int, int);
int add(double, double);
int (*pf3) (int, int) = add; //pf3指向int add(int, int)
编译器通过指针类型决定使用哪个函数,指针类型必须与重载函数中的某一个精确匹配(返回类型,形参类型都完全匹配)。
5 返回指向函数的指针
使用typedef定义的类型别名 声明
typedef int (*PF) (int, int);
using PF2 = int (int, int); //另一种等价方式,PF2是指针类型
using F = int (*) (int, int); // F是函数类型
PF func4(int);
也可以直接声明
int (*func4(int))(int, int);
按照由内向外的顺序阅读此声明语句。func4 有形参列表,则func4是一个函数,其形参为 (int),func4 前面有 * ,所以 func4 返回一个指针,指针本身也包含形参列表(int,int),因此指针指向函数,该函数的返回值为int.
总结:func4 是一个函数,形参为(int),返回一个指向int(int,int)的函数指针。
6 C++函数指针
由于C++完全兼容C,则C中可用的函数指针用法皆可用于C++
6.1 C++其他函数(指针)定义方式及使用
6.1.1 typedef与decltype组合定义函数类型
typedef decltype(add) add2;
decltype返回函数类型, add2是与add相同类型的函数,不同的是add2是类型,而非具体函数。
6.1.2 使用方法
add2* pf;//pf指向add类型的函数指针,未初始化
typedef与decltype组合定义函数指针类型
typedef decltype(add)* PF2; //PF2与PF意义相同
PF2 pf; // pf指向int(int,int)类型的函数指针,未初始化
使用推断类型关键字auto定义函数类型和函数指针
auto pf = add;
auto *pf
注意事项
指向不同函数类型的指针不存在转换规则。即一个函数指针只能指向其定义的函数类型。
//对于两个不同函数类型的函数
int add(int, int); //函数类型是 int (int, int)
int add2(double, double); //函数类型是 int (double, double)
double add3(int, int); //函数类型是 double (int, int)
int (*pf)(int, int); //函数指针 pf 只能指向int (int, int)类型的函数
pf = 0; //可以为pf 赋值一个nullptr 或者 0,表示没有指向任何一个函数
pf = add; //正确,
pf = add2; //错误, 形参类型不匹配
pf = add3; //错误,返回类型不匹配