简介

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

  1. bool lengthCompare(const string &, const string &);
  2. // pf是一个未初始化的函数指针: 参数是两个const string的引用, 返回值是bool类型
  3. bool (*pf) (const string &, const string &);

把函数名作为一个值时, 该函数自动转换成指针:

  1. // pf指向名为lengthCompare的函数
  2. pf = lengthCompare;
  3. // 等价写法
  4. pf = &lengthCompare;

我们可以使用函数指针调用该函数:

  1. // 等价的三种写法
  2. bool b1 = pf("tomo", "cat");
  3. bool b2 = (*pf)("tomo", "cat");
  4. bool b3 = lengthCompare("tomo", "cat");

函数指针形参

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

  1. // 第三个参数是函数类型, 它会自动转换成函数指针
  2. void useBigger(const string &s1, const string &s2,
  3. bool pf(const string &, const string &));
  4. // 等价声明: 显式将形参定义成函数指针
  5. void useBigger(const string &s1, const string &s2,
  6. bool (*pf) (const string &, const string &));

我们可以使用类型别名和decltype来简化使用了函数指针的代码:

Tips:decltype返回函数类型,此时不会将函数类型自动转换成指针类型,只有在结果前面加上*才能得到函数指针。

  1. // Func1和Func2是函数类型
  2. typedef bool Func1(const string&, const string&);
  3. typedef decltype(lengthCompare) Func2;
  4. // FuncP1和FuncP2是函数指针类型
  5. typedef bool(*FuncP1)(const string&, const string&);
  6. typedef decltype(lengthCompare) *FuncP2;
  7. // 使用类型别名简化useBigger函数的声明
  8. void useBigger(const string&, const string&, Func1);
  9. void useBigger(const string&, const string&, Func2);
  10. void useBigger(const string&, const string&, FuncP1);
  11. void useBigger(const string&, const string&, FuncP2);

返回指向函数的指针

1. 类型别名using简化返回函数指针的函数声明

一般情况下直接声明返回函数指针的函数比较复杂:

  1. // foo参数为int, 返回值是int(*)(int*, int)的函数指针
  2. int (*foo(int))(int*, int);

新标准下我们可以使用using关键字定义类型别名:

  1. // F是函数类型而非函数指针类型
  2. using F = int(int*, int);
  3. // PF是函数指针类型
  4. using PF = int(*)(int*, int);

有了类型别名我们可以将foo函数重新声明为:

  1. // foo接收int类型作为参数, 返回PF的函数指针
  2. PF foo(int);
  3. // 等价写法
  4. F *foo(int);

2. 尾置返回类型

前面提到的foo函数还有另外一种声明方式:

  1. auto foo(int) -> int(*)(int* int);