函数指针声明必须严格匹配目标函数签名,包括参数类型、数量、返回类型和调用约定;C++ 不支持隐式转换;正确写法为 int (*func_ptr)(int, double) = &some_func;成员函数需用 std::function 或成员指针语法;推荐用 using 定义类型别名提升安全性;函数指针无法捕获局部变量,需用 std::function 或 lambda 实现闭包效果。

函数指针声明必须匹配目标函数的签名
函数指针不是万能容器,它和目标函数的参数类型、数量、返回类型、调用约定(如 __cdecl 或 __stdcall)必须严格一致,否则编译失败或运行时崩溃。C++ 不做隐式转换,哪怕只差一个 const 或引用符号都会报错。
- 正确写法:
int (*func_ptr)(int, double) = &some_func;,前提是some_func确实声明为int some_func(int, double); - 常见错误:把
void func(int&)赋给void (*)(int)—— 引用参数和值参数不兼容 - 成员函数不能直接赋给普通函数指针,需改用
std::function或成员指针语法ReturnType (Class::*)(Args...)
调用时加不加 & 和 * 都可以,但含义不同
函数名本身在多数上下文中会自动退化为函数指针,所以 func_ptr、&func_ptr、*func_ptr 在调用时效果一样,但语义和可读性差别很大。
-
func_ptr(1, 2.0);—— 最常用,清晰表明这是指针调用 -
(*func_ptr)(1, 2.0);—— 显式解引用,强调“通过指针间接调用”,适合教学或强调语义 -
(&func_ptr)(1, 2.0);—— 错误!这是取函数指针变量自身的地址(变成二级指针),编译不过
用 typedef 或 using 提前定义类型更安全
裸写函数指针声明容易出错,括号位置一错就变成“返回函数指针的函数”,而不是“指向函数的指针”。用类型别名能大幅降低出错率。
- 传统写法:
typedef int (*CalcFunc)(int, int); CalcFunc op = &add; - 现代写法:
using CalcFunc = int (*)(int, int); CalcFunc op = &add; - 避免这种写法:
int *func(int, int);—— 这是函数声明,返回int*,不是函数指针类型
函数指针不能跨作用域捕获局部变量
函数指针只能指向具名函数(全局、静态、命名空间作用域),无法携带上下文。如果需要类似“闭包”的行为,函数指针无能为力,必须换方案。
立即学习“C++免费学习笔记(深入)”;
- 想传参又不想每次都显式传?用
std::bind或 lambda 包装后转成std::function - 例如:
auto bound = std::bind(add_with_offset, _1, _2, 10);,然后存进std::function<int></int> - 硬要用函数指针?只能把状态提成全局/静态变量——不推荐,破坏封装且线程不安全


















