函数指针
详情可参见 《C++ Primer(第五版)》 221页
顾名思义,函数指针就是指向函数的指针
与其他指针一样函数指针需要有类型限制,函数指针的类型由返回值类型与形参类型共同决定, eg:
bool (*pF)(const string&, const int);
/*
*pF外面的括号不可省略,否则就会被认为是一个返回值类型为bool* 的函数
*/
指针pF指向一个函数,该函数返回值类型为void,形参列表为一个const string&, 一个const int
一、函数指针的使用
bool equal(const string&, const int);//这是一个函数的声明
pF = equal;
pF = &equal;
//上面两种方法均可以表示指针pF指向equal
bool (*pF2)(const string&, const int) = equal; //声明函数指针同时赋值
bool b1 = pF("hello",5);
bool b2 = (*pF)("hello",5);//提前解引用指针
bool b3 = equal("hello",5);
//上面三种调用函数的方法等价,可以看到,我们在使用函数指针时可以不用提前解引用指针
指向不同类型函数的指针没有相互转化规则,但是我们可以将一个函数指针赋值为空
,或者0
,表示该指针没有指向任何函数
pF = nullptr;
pF = 0;
二、函数指针形参
当我们想在一个函数中使用其他函数时,我们可以传递函数的地址 eg:
bool isEqual(vector<int>&arr, void (*func1)(vector<int>&), void (*func2)(vector<int>&));
bool isEqual(vector<int>&arr, void func1(vector<int>&), void func2(vector<int>&)); //也可
//调用
bool flag = isEqual(arr1,sort1,sort2);
//sort1,sort2是两个函数名
//在函数内部,直接用func1,func2
bool isEqual(vector<int>&arr1, void (*func1)(vector<int>&), void (*func2)(vector<int>&))
{
vector<int> arr2(arr1);
func1(arr1);
func2(arr2);
//...
}
ps:利用typedef和decltype进行简化
从上面的代码中我们可以看出,在函数中直接使用函数指针作为参数列表会显得冗长,所以我们可以同typedef起类型别名的方式进行简化 eg:
typedef void (*func1)(vector<int>&);
typedef void (*func2)(vector<int>&);
上面的函数声明就可以简化为
bool isEqual(vector<int>&arr1, func1, func2);
三、返回指向函数的指针
与数组相同,我们不能返回一个数组,但是可以返回一个指向1数组的指针;我们不能返回函数,但是可以返回一个指向函数的指针
想要返回指针,那么返回值必然是指针类型,但是编译器不会自动地将函数返回类型当成对应的指针处理
int(*)(int,int) func(int i); //这种写法编译器无法看懂
最简单的办法是使用类型别名
using PF = int (*)(int, int); //PF为函数指针类型
using F = int(int,int); //F为函数型
PF f1(int); //yes
F f2(int) //no, we cannot return a function
F* f3(int) //yes, we will return a pointer to a function
另一种方法是直接声明(不建议使用,会很乱)
int (*f4(int))(int, int);
/*
通过cpp常用的由内到外的阅读方式
f4有形参列表,所以f4是一个函数,f4前面是个*,所以f4返回的是一个指针,该指针本身也包含形参列表,因此该f4指向一个函数,返回值类型为int,故f4是个函数指针
*/
还有一种方法是尾置返回类型
auto f5(int) -> int (*)(int,int);