C++ 函数指针:把"函数"当"值"传来传去
函数指针就是指向函数的指针变量。函数在内存里同样有地址,所以可以像变量一样被指针"指向",进而作为参数传递、存到数组里、运行时切换调用。
一、声明函数指针
语法:返回类型 (*指针名)(参数列表);
1 |
|
调用时
ptr(...)和(*ptr)(...)完全等价,编译器都把它当成"解引用后再调用"。
为什么要写 (*ptr) 不直接写 *ptr(...)?
因为小括号 () 优先级最高,*ptr(4.2, 1.5) 会被解读成 *(ptr(4.2, 1.5))——"对函数返回值解引用",显然不对。所以外层括号必须括起来。
二、用 typedef / using 给函数指针起别名
每次写 double (*FuncPtr)(double, double) 又臭又长,建议起个别名。
typedef(C 风格)
1 |
|
using(C++11 风格,更推荐)
1 | using FuncPtr = double (*)(double, double); |
using写法更清晰,可读性也好。现代 C++ 优先用using。
三、定义"函数类型"再取指针
也可以先定义函数类型(不带 *),再声明指针:
1 | typedef double FuncType(double, double); // FuncType 是函数类型 |
注意:FuncType 是函数类型,FuncType* 才是指针。这种写法较少用,了解即可。
四、用 auto 简化
函数指针声明往往很长,能用 auto 就用 auto:
1 | auto ptr = add; |
限制:
auto只能在声明时初始化单个变量时用。声明函数指针数组就不能用auto,必须用typedef/using。
五、函数指针数组
1 | typedef double (*FuncPtr)(double, double); |
实际工程里这种"分发表"用
std::function或std::map<std::string, fnPtr>代替更灵活;函数指针数组更多出现在 C / 嵌入式代码里。
六、作为函数参数(回调函数)
函数指针最常见的用途——把"行为"作为参数传给另一个函数:
1 |
|
输出:
1 | 0.07 0.1 1.9 2 3.14 4.7 5.6 |
sort的第三个参数就是「比较函数指针 / 可调用对象」,这就是典型的回调函数场景。
七、类成员函数指针
类成员函数指针的语法跟普通函数指针不一样——前面要带类名限定。
1 |
|
调用语法
| 调用方式 | 语法 |
|---|---|
| 通过对象 | (对象.*成员函数指针)(参数...) |
| 通过对象指针 | (对象指针->*成员函数指针)(参数...) |
成员函数指针比普通函数指针复杂得多——实际工程里几乎都用
std::bind或 lambda 捕获代替,可读性更好。
八、易错点清单
- 声明少写括号:
double *ptr(double, double)会被当成「返回double*的函数声明」,而不是「指向返回 double 的函数指针」。永远要把*ptr用括号包起来。 - 函数指针类型不匹配:参数列表或返回值类型对不上,编译直接报错。
int (*)(int)和int (*)(double)是完全不同的类型。 - 空指针解引用调用:
double (*ptr)(double, double) = nullptr; ptr(1, 2);→ 崩溃。调用前判断:if (ptr) ptr(...);。 - 成员函数指针忘了
&和.*/->*:赋值要&类名::函数名;调用要(obj.*ptr)(...)或(p->*ptr)(...)。 typedef函数指针时漏掉*:typedef double (FuncPtr)(double, double);定义的是函数类型而不是指针,要写typedef double (*FuncPtr)(double, double);。
九、极简速记
| 场景 | 推荐写法 |
|---|---|
| 普通函数指针 | using FuncPtr = double (*)(double, double); |
| 局部变量 | auto ptr = func; |
| 函数指针数组 | FuncPtr arr[] = {f1, f2}; |
| 成员函数指针 | double (Class::*ptr)(...) = &Class::method; |
| 调用 | ptr(...) / (*ptr)(...) / (obj.*ptr)(...) |
十、小结
- 函数指针 = 指向函数的指针变量,让"行为"也能像值一样传递;
- 语法核心:
返回类型 (*名字)(参数列表),*一定要包进括号; - 别名优先用
using;局部变量优先用auto; - 主要用途是回调函数(STL 算法、qsort、自定义 API 等);
- 成员函数指针语法复杂、坑多,实际工程优先用
std::function或 lambda 替代。

