6.7 函数指针
函数指针指向的是函数而非对象。
函数指针指向某种特定的类型,函数的类型由它的返回类型和形参类型共同决定,与函数名无关。如
bool lengthCompare(const string&, const string&);
该函数的类型是
bool(const string&, const string&)
声明一个指向该函数的指针
bool (*pf)(const string&, const string&); // pf 指向一个函数,该函数的参数是两个 const string 的引用,返回值是 bool 类型
使用函数指针
当我们把函数名作为一个值使用时,该函数自动地转换成指针。
pf = lengthCompare; // pf 指向名为 lengthCompare 的函数
pf = &lengthCompare; // 等价的赋值语句,取地址符是可选的
可以直接使用指向函数的指针调用该函数,无需提前解引用指针
bool b1 = pf("hello", "goodbye"); // 调用 lengthCompare 函数
bool b2 = (*pf)("hello", "goodbye"); // 一个等价的调用
bool b3 = lengthCompare("hello", "goodbye"); // 另一个等价的调用
在指向不同函数类型的指针间不存在转换规则。
可以为函数指针赋一个 nullptr 或者值为 0 的整形常量表达式,表示该指针没有指向任何一个函数
string::size_type sumLength(const string&, const string&);
bool cstringCompare(const char*, const char*);
pf = 0;
pf = sumLength; // 错误:返回类型不匹配
pf = cstringCompare; // 错误:形参类型不匹配
pf = lengthCompare; // 正确:函数和指针的类型精确匹配
重载函数的指针
如果定义了指向重载函数的指针,编译器通过指针类型决定选用哪个函数,指针类型必须与重载函数中的某一个精确匹配。
函数指针形参
不能定义函数类型的形参,但是形参可以是指向函数的指针。此时,形参看起来是函数类型,实际上却是当成指针来用
// 第三个形参是函数类型,它会自动地转换成指向函数的指针
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&));
可以直接把函数作为实参使用,此时它会自动地转换成指针
// 自动将函数 lengthCompare 转换成指向该函数的指针
useBigger(s1, s2, lengthCompare);
类型别名和decltype
能简化使用函数指针的代码
// Func 和 Func2 是函数类型
typedef bool Func(const string&, const string&);
typedef decltype(lengthCompare) Func2; // 等价的类型
// FuncF 和 FuncF2 是指向函数的指针
typedef bool (*FuncF)(const string&, const string&);
typedef decltype(lengthCompare) *FuncF2;
// 重新声明 useBigger
void useBigger(const string&, const string&, FuncF);
void useBigger(const string&, const string&, FuncF2);
返回指向函数的指针
不能返回一个函数,但可以返回指向函数类型的指针。此时必须把返回类型写成指针形式,编译器不会自动地将函数返回类型当成对应的指针类型处理。
using F = int(int*, int); // F 是函数类型,不是指针
using pF = (int*)(int*, int); // pF 是指针类型
pF f1(int); // 正确:pf 是指向函数的指针,f1 返回指向函数的指针
F f1(int); // 错误:F 是函数类型,f1 不能返回一个函数
F *f1(int); // 正确:显式的指定返回类型
auto f1(int)->int (*)(int*, int);
将 auto 和 decltype 用于函数指针类型
如果明确知道返回的函数是哪一个,可以使用decltype
简化书写函数指针返回类型的过程.
string::size_type sumLength(const string&, const string&);
string::size_type largeLength(const string&, const string&);
// 根据其形参的取值,getFcn 函数返回指向 sumLength 或者 largeLength 的指针
decltype(sumLength) *getFcn(const string&);