函数指针

函数指针指向的是函数而非对象.和其他指针一样,函数指针指向某种特定类型.函数的类型由它的返回类型和形参类型共同决定,与函数名无关.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool lengthCompare(const string &a, const string &b) {
return a.size() < b.size();
}

bool (*pf)(const string &a, const string &b); // pf是一个未初始化的函数指针
bool (*pf1)(const string &a, const string &b); // pf1是一个未初始化的函数指针

int main(){
// 以下两种写法都是等价的
pf = lengthCompare;
pf1 = &lengthCompare;

// 以下是三个等价的调用
bool fa = pf("hello", "goodbye");
bool fb = pf1("hello", "goodbye");
bool fc = lengthCompare("hello", "goodbye");
return 0;
}

当把函数名作为一个值使用时,该函数自动转换为指针,所以, pf = lengthCompare和 pf1 = &lengthCompare是等价的.

函数指针作为实参

不能定义函数类型的形参,但是形参可以是指向函数的指针

1
2
3
4
5
// 第三个形参是函数类型,它会自动转换为指向函数的指针
void useBigger(const string &s1, const string &s2, bool pf(const string &, const string &));

// 显式地将形参定义为指向函数的指针
void useBigger(const string &s1, const string &s2, bool (*pf)(const string &, const string &));

定义函数类型别名和函数指针类型别名

decltype返回函数类型,不会将函数类型自动转换为指针类型

1
2
3
4
5
6
7
8
// Func和Func2是函数类型
typedef bool Func(const string &, const string &);
typedef decltype(lengthCompare) Func2; // 等价的类型


// FuncP和FuncP2是指向函数的指针
typedef bool (*FuncP)(const string &, const string &);
typedef decltype(lengthCompare) *FuncP2;

useBigger的另外两种等价的声明(使用了类型别名)

1
2
void useBigger(const string &s1, const string &s2,Func);
void useBigger(const string &s1, const string &s2,FuncP2);

返回函数指针

1
2
using F = int(int*, int);		// F是函数类型,不是指针
using PF = int(*)(int*,int); // PF是指针类型

使用类型别名定义返回类型为函数指针的函数

1
2
3
4
5
6
7
PF f1(int);		// PF是指向函数的指针,f1返回指向函数的指针
F f1(int); // F是函数类型,f1不能返回一个函数类型
F* f1(int); // F*是函数类型
int (*f1(int))(int *,int); // 直接声明f1

// 尾置返回类型
auto f1(int) -> int(*)(int *,int);

首先f1有形参列表,所以,f1是个函数,f1的返回值是一个指针。该指针也有形参列表,所以,该指针指向函数。此指针指向的函数的形参是int*和int,返回int。所以,f1是一个返回一个函数int(*)(int *,int)的函数

一个复杂点的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
string::size_type sumLength(const string &a, const string &b) {
return a.size() + b.size();
}

string::size_type largerLength(const string &a, const string &b) {
return a.size() > b.size() ? a.size() : b.size();
}

decltype(sumLength) *getFcn(const string &s) {
if (s == "+") {
return sumLength;
} else {
return largerLength;
}
}

int main(){
typedef string::size_type (*Func)(const string &, const string &);
Func fcn = getFcn("+"); // fcn是一个函数指针

// 一种等价形式
// auto fcn = getFcn("+");

string::size_type sz = fcn("hello", "good");
cout << sz << endl;

fcn = getFcn("-");
sz = fcn("hello", "good");
cout << sz << endl;
return 0;
}

由于函数的类型由它的返回类型和形参类型决定,而与函数名无关,可知sumLength和largerLength属于相同的类型。所以,我们可以向getFcn传入参数,获取指向同一种函数类型的不同的函数指针。