C++中如何正确向遍历函数传递成员函数引用
错误原因
非静态成员函数存在隐式的this指针入参,你代码中print作为foo类的非静态const成员函数,实际签名等效于void(const foo*, int),和traverse要求的void(*)(int)普通函数指针类型完全不匹配,因此traverse(&print)语句会报类型不兼容的编译错误。
可行解决方案
下面按灵活性从高到低给出三种常用实现方案:
方案1:使用
std::function兼容任意可调用对象(最推荐,适配解耦需求)
这种方案可以支持成员函数、lambda、普通函数、仿函数等任意符合调用签名的visitor,完美实现遍历逻辑和visitor的解耦,是C++11及以上版本的标准实现方式。
修改后的代码示例:#include <functional> #include <iostream> using namespace std; class foo { public: foo() {}; ~foo() {}; void print(int x) const { //visitor cout << x << endl; } // 用std::function替代普通函数指针 void traverse(std::function<void(int)> visitor) { for (int i = 0; i < 9; i++) visitor(myAry[i]); } void printAll() { // 方式1:用lambda捕获this调用成员函数 traverse([this](int x) { print(x); }); // 方式2:用std::bind绑定实例和参数 // traverse(std::bind(&foo::print, this, std::placeholders::_1)); } int myAry[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; };你甚至可以将visitor作为参数从
foo类外部传入,完全剥离遍历逻辑和具体visitor的耦合,适配你doubly-threaded BST的多遍历、多visitor的需求。方案2:将visitor成员函数改为静态成员
静态成员函数没有隐式this指针,签名和普通函数指针匹配,如果你所需的visitor不需要访问类的非静态成员,可以用这种最简方案:class foo { public: // 加static修饰符 static void print(int x) { cout << x << endl; } void traverse(void (*visitor)(int)) { for (int i = 0; i < 9; i++) visitor(myAry[i]); } void printAll() { traverse(&foo::print); } };缺点是静态成员函数无法访问类的非静态成员变量/函数,适用场景有限。
方案3:C风格上下文传参(无STL依赖场景)
如果你需要兼容无C++标准库的场景,可以给visitor增加上下文指针参数,把当前实例作为上下文传入:class foo { public: void print(int x) const { cout << x << endl; } // 增加上下文参数 void traverse(void (*visitor)(int, void*), void* ctx) { for (int i = 0; i < 9; i++) visitor(myAry[i], ctx); } void printAll() { traverse([](int x, void* ctx) { static_cast<const foo*>(ctx)->print(x); }, (void*)this); } };缺点是类型不安全,需要手动做指针转换,代码冗余度高。
内容的提问来源于stack exchange,提问作者ToTheStars_1138
相关产品推荐
相关产品推荐

