<p>最稳妥方式是用 std::function 包装成员函数,配合 std::bind 或 lambda 绑定对象;原始成员函数指针语法复杂、易错,需严格匹配签名并显式提供 this 上下文,调用必须用 . 或 -> 运算符。</p>

用 std::function + std::bind 绑定成员函数指针最稳妥
直接用原始成员函数指针调用,语法绕、易出错,尤其涉及 this 指针时。现代 C++ 更推荐用 std::function 包装,再配合 std::bind 或 lambda 绑定实例对象。
-
std::function<void></void>可以统一接收普通函数、lambda、绑定后的成员函数,类型安全且调用方式一致 -
std::bind(&MyClass::func, &obj, std::placeholders::_1)把&obj和占位符绑定后,得到一个可调用对象,后续只传参数即可 - 若用 lambda:
[&obj](int x) { obj.func(x); }更直观,捕获方式要小心生命周期——别捕获已销毁对象的引用 - 原始成员函数指针写法是
void (MyClass::*)(),调用必须用(obj.*ptr)()或(ptr_obj->*ptr)(),漏掉括号或点星号顺序就编译失败
原始成员函数指针的声明和调用必须严格匹配签名
成员函数指针不是普通函数指针,它隐含 this 参数,声明时必须带类作用域,调用时必须显式提供对象上下文。
- 声明:
void (MyClass::*ptr)(int) = &MyClass::doSomething;—— 注意括号位置,MyClass::*是整体修饰符 - 调用:
(obj.*ptr)(42)(对对象)或(pObj->*ptr)(42)(对指针),.*和->*是专用运算符,不能替换成.或-> - const 成员函数需用
void (MyClass::*ptr)(int) const声明,否则无法赋值 - static 成员函数可直接用普通函数指针,不用特殊语法,但那就不是“成员函数指针”了
在容器或回调中存成员函数指针,优先选 std::function 而非裸指针
想把多个对象的不同成员函数存进 std::vector<:function>> </:function>?裸成员函数指针做不到,因为类型不兼容(每个类+函数组合产生唯一类型)。
-
std::function会做类型擦除,允许不同类、不同签名(只要适配)统一存入同一容器 - 用 lambda 绑定时注意:捕获局部对象地址可能悬空;建议捕获
shared_ptr或确保对象生命周期长于std::function存续期 - 性能上,
std::function有轻微开销(通常一次间接跳转),但远低于手写虚函数或多态设计的复杂度 - 如果硬要用裸指针,只能为每种
Class::Func单独定义容器,维护成本高,基本没人这么干
常见错误:忘记解引用或搞错调用语法
编译报错如 error: must use '.*' or '->*' to call pointer-to-member function,就是试图像普通函数那样调用成员函数指针。
立即学习“C++免费学习笔记(深入)”;
- 写成
ptr(42)❌ —— 缺对象上下文,连编译都不过 - 写成
obj.ptr(42)❌ ——.不能用于成员指针,语法非法 - 写成
(obj.*ptr)(42)✅ —— 正确,括号不能省,.*是单个运算符 - 写成
obj->*ptr(42)❌ —— 运算符优先级导致等价于obj->*(ptr(42)),错 - 若
ptr是空(未初始化),调用会崩溃,原始指针无空值检查,std::function调用前可用if (f)判空
std::function + lambda 就行,少踩坑,也更易读。


















