C++中类成员函数指针与std::bind的用法详解
在C++开发中,处理类成员函数指针以及使用std::bind进行函数绑定是高级编程中的常见需求。本文将展示如何定义类成员函数指针、如何通过实例调用成员函数,以及如何将绑定的函数存入map容器中进行统一管理和调用,适用于需要动态绑定行为或实现回调机制的场景。
目标:管理类成员函数的动态调用
要实现的功能包括:
- 直接传递成员函数指针:获取类的静态成员函数指针并进行调用。
- 绑定成员函数:使用
std::bind将成员函数与具体的对象实例(this)结合,生成一个类似普通函数的可调用对象。 - 容器存储与批量调用:将生成的可调用对象存入
std::map,并通过迭代器遍历执行。
准备条件:包含必要头文件
示例代码依赖于标准模板库(STL)中的算法、映射容器和功能对象模块:
#include <algorithm>
#include <map>
#include <string>
#include <functional>
#include <iostream>
// 若使用ATL/MFC环境,可能需要 <atltrace.h>
第1步:定义类结构与成员变量
首先定义一个测试类TestClass,包含一个用于演示的成员函数Sub,以及一个用于存储绑定后函数的成员变量m_mapFun。
- 成员函数:
int Sub(int x, int y),返回两数之差。 - 存储容器:
std::map<std::string, std::function<int (int, int)>> m_mapFun,键为名称,值为接受两个int参数并返回int的可调用对象。
第2步:使用成员函数指针直接调用
在PrintWithClassMemberFunction中,演示如何使用指向成员函数的指针int (TestClass::*f)(int, int)。注意,调用成员函数指针时必须配合对象实例(this)。
复制代码 代码如下:
class TestClass {
public:
int Sub(int x, int y) {
return y - x;
}
void InitAndTest() {
// 方法1:直接通过成员函数指针调用
PrintWithClassMemberFunction(&TestClass::Sub);
// 方法2:通过指针实例调用
PrintWithClassPointer(this);
}
// 接收成员函数指针作为参数
void PrintWithClassMemberFunction(int (TestClass::*f)(int, int)) {
// 关键:使用 this 指针和 .* 运算符调用成员函数
auto rel = (this->*f)(12, 13);
printf("[%d]\n", rel); // 输出: 1
// 将成员函数指针绑定到当前对象 this,并保留前两个参数位置由占位符占据
// std::placeholders::_1, _2 对应 Sub 的参数 x, y
auto funBind = std::bind(f, this, std::placeholders::_1, std::placeholders::_2);
m_mapFun["DirectPtr"] = funBind;
}
void PrintWithClassPointer(TestClass *pointInstance) {
// 通过普通指针调用
auto rel = pointInstance->Sub(20, 30);
printf("[%d]\n", rel); // 输出: 10
// 使用 std::bind 绑定特定实例 pointInstance
auto funBind = std::bind(&TestClass::Sub, pointInstance, std::placeholders::_1, std::placeholders::_2);
m_mapFun["PointerInst"] = funBind;
}
private:
std::map<std::string, std::function<int (int, int)>> m_mapFun;
};
这里的核心在于(this->*f)(...)语法,这是C++中解引用成员函数指针的标准方式。
第3步:批量调用绑定的函数
在CallBindFun中,展示如何遍历map并执行所有已绑定的函数。使用std::for_each配合Lambda表达式来简化代码。
复制代码 代码如下:
void CallBindFun(int a, int b) {
std::for_each(
m_mapFun.begin(),
m_mapFun.end(),
[&a, &b](decltype(*m_mapFun.begin()) it) {
// it.first 是键名, it.second 是 std::function
printf("[%s] %d\n", it.first.c_str(), it.second(a, b));
}
);
}
第4步:主函数运行测试
创建对象并依次执行初始化和绑定测试,最后调用绑定的函数查看结果。
复制代码 代码如下:
int main() {
TestClass tc;
tc.InitAndTest(); // 初始化并添加至 map
tc.CallBindFun(64, 128); // 批量执行,传入参数 64, 128
return 0;
}
完成判断
运行程序后,控制台应输出以下内容,验证函数指针调用和bind绑定均成功:
[1]
[10]
[DirectPtr] 64 // 128 - 64
[PointerInst] 64 // 128 - 64
结果一致说明两种绑定方式均正确捕获了上下文并执行了逻辑。
简要总结
C++中类成员函数指针的调用必须依赖对象实例。当需要将成员函数作为通用回调或存储在容器中时,std::bind是极佳的选择,它可以将this指针和固定参数提前绑定,从而生成无参或仅含变长参数的可调用对象。以上关于C++传递函数指针和bind的详细内容,更多关于C++高级编程的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









