typedef 和 using 均可定义函数指针类型,后者更直观且支持模板别名;函数指针要求签名严格匹配,包括参数类型、const、引用及调用约定,否则编译失败。

用 typedef 定义函数指针类型最直观
直接写函数指针声明容易看花眼,比如 int (*func_ptr)(int, char*),每次声明变量都要重复这套语法。用 typedef 把它“起个名字”,后续使用就和普通类型一样清晰。
-
typedef int (*FuncType)(int, char*)—— 这定义了一个叫FuncType的类型,代表“指向接受int和char*、返回int的函数”的指针 - 之后可以自然地写
FuncType p = &some_function或FuncType p = some_function(函数名自动退化为指针) - 注意:
typedef语句末尾必须有分号,漏掉会编译报错expected ';' before 'p'
C++11 起推荐用 using 替代 typedef
using 语法更符合直觉,尤其是函数签名复杂时,可读性明显提升。
-
using FuncType = int (*)(int, char*)—— 等价于上面的typedef,但类型名在左边,箭头感更强 - 支持模板别名:
template<typename t> using Callback = void (*)(T)</typename>,而typedef无法直接做到这点 - 若混用
const,比如想定义“指向 const 成员函数的指针”,using的括号位置更不易出错
函数指针类型必须严格匹配参数和返回值
哪怕只差一个 const、一个引用或调用约定(如 __stdcall),编译器就认为是不同类型,赋值会失败。
- 错误示例:
void f(int)和void f(const int)在 C++ 中参数类型不等价,void (*p)(const int)不能指向前者 - 成员函数指针不是普通函数指针:
int (MyClass::*)()和int (*)()完全不兼容,不能用同一个类型别名表示 - 返回引用或数组的函数,声明时括号不能省:
int (&(*)())[5]表示“指向返回 int[5] 引用的函数”,少一对括号就会被解析成别的意思
实际传参和存储场景下要注意生命周期
函数指针本身很小(通常 4 或 8 字节),但它的目标函数必须在调用时仍有效。这点在回调、事件注册或 lambda 封装中极易出错。
立即学习“C++免费学习笔记(深入)”;
- 不要把局部函数(如嵌套在 if 块里的 static 函数)的地址存到全局函数指针里——它可能根本没生成符号,或链接时报
undefined reference - lambda 只有不捕获时才能隐式转成函数指针;一旦用了
[x]或[&],就必须用std::function,不能再用原生函数指针类型 - 动态库中导出函数时,确保函数声明和 typedef 类型的调用约定一致,Windows 下常见
__cdecl与__stdcall混用导致栈不平衡
const、或忽略调用约定差异,都会让编译器拒绝你,而且错误信息往往指向赋值行而非 typedef 行——这时候得倒回去逐字符核对括号匹配和修饰符顺序。


















