本文内容为《C++ Primer(第五版)》第六章第7节 函数指针 整理而得。
函数指针及其声明※
- 函数指针指向的是函数而非对象,它指向某种特定的类型。
- 函数的类型由它的
返回类型和形参类型共同决定,与函数名无关,例如:bool LengthCompare(const std::string&, const std::string&);该函数的类型是
bool(const std::string&, std::string&)。要声明一个指向该函数的指针,只需要用指针替换函数名即可:bool (*pf)(const std::string&, const std::string&);注意:
- 此时只是声明,并未初始化。
- pf两端的括号不可少,若缺少括号,则pf是一个返回值为
bool*的函数。
使用函数指针※
把函数名作为一个值使用时,该函数自动转换为指针,例如:
pf = LengthCompare;
/// 等价于
pf = &LengthCompare;使用时无需提前解引用函数指针:
bool b1 = pf("hello", "goodbye");
/// 等价于
bool b1 = (*pf)("hello", "goodbye");
/// 等价于
bool b1 = LengthCompare("hello", "goodbye");函数指针形参※
与数组类型,函数指针可以作为形参使用。例如:
void UseBigger(const std::string& str1, const std::string& str2
, bool pf(const std::string&, const std::string&));
/// 等价于
void UseBigger(const std::string& str1, const std::string& str2
, bool (*pf)(const std::string&, const std::string&));也可以直接将函数作为实参使用,它会自动转换成指针:
void UseBigger(s1, s2, LengthCompare);但是,直接使用函数指针类型会显得冗长繁琐,因此可以使用类型别名和decltype来简化代码:
typedef bool Func(const std::string&, const std::string&);
/// 等价于
typedef decltype(LengthCompare) Func2;此时,Func和Func2是函数类型。
typedef bool (*FuncP)(const std::string&, const std::string&);
/// 等价于
typedef decltype(LengthCompare) *FuncP2;此时,FuncP和FuncP2是指针类型。
返回函数指针※
和数组类似,不能直接返回一个函数,但是能返回指向函数的指针(即:函数指针),但是我们必须要把返回类型写成只找你的形式,因为编译器不会自动地将函数返回类型当成对应的指针类型。
声明一个返回函数指针的函数,最简单的办法是使用类型别名:
using F = int(int*, int); /// 此时,F是函数类型,不是指针 using PF = int(*)(int*, int); /// PF是指针类型使用函数指针
PF f1(int); /// 正确,这里要注意:f1的参数int与PF的两个int没关系,这是f1这个函数功能的形参 F f1(int); /// 错误:F是函数类型,f1不能返回函数类型 F *f1(int); /// 正确,显示指明指针 int (*f1(int))(int*, int); /// 这样的声明也是正确的,且这是最原始的声明方法,就是不好阅读C++11还有一种返回类型的方式:位置返回
auto f1(int) -> int(*)(int*, int);- 使用函数指针的场景
- 动态切换函数逻辑(策略模式)
- 回调函数注册
将auto和decltype用于函数指针类型※
假定有两个函数如下:
std::string::size_type SumLength(const std::string&, const std::string&);
std::string::size_type LargerLength(const std::string&, const std::string&);可以定义一个函数,用来返回前两个函数中的一个:
decltype(SumLength) *getFunc(const std::string&); /// 这里getFunc的参数并不一定是这样的,只是作为一个判断要返回哪个函数的依据。
/// 等价于
decltype(LargerLength) *getFunc(const std::string&);
/// 等价于
std::string::size_type (*getFunc(const std::string&))(const std::string&, const std::string&);