如何将C++非静态成员函数传入ftw函数?
解决C++中
ftw无法调用非静态成员函数的问题 嘿,这个问题我当初刚学C的时候也碰到过!核心原因是C非静态成员函数默认会携带this指针作为隐式参数,而ftw要求的是不带额外上下文的普通C风格函数指针,所以直接传成员函数肯定不行。下面给你几个实用的解决办法,按推荐程度排序:
方案1:用nftw替代ftw(首推)
ftw是比较老旧的文件遍历函数,它的升级版nftw(Linux/macOS等主流系统都支持)提供了传递自定义上下文的能力——它的最后一个参数可以传入任意void*类型的数据,正好用来传递你的Foo类实例指针,完美绕过函数指针的限制:
#include <iostream> #include <sys/types.h> #include <sys/stat.h> #include <ftw.h> class Foo { public: int func1(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { total += sb->st_size; std::cout << total << std::endl; return 0; } int func2() { // 传入当前实例指针作为上下文,静态成员函数作为回调 return nftw("plots", staticCallback, 3, FTW_PHYS, this); } private: // 静态成员函数,完全符合nftw的回调签名要求 static int staticCallback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { // 把上下文转换回Foo实例指针,调用目标成员函数 Foo* self = reinterpret_cast<Foo*>(ftwbuf->__ftw_buf); return self->func1(fpath, sb, typeflag, ftwbuf); } int total = 0; };
方案2:线程局部存储(Thread Local Storage)+ 静态成员函数
如果你的场景不能切换到nftw,这个方案比全局变量安全得多——每个线程会有独立的实例指针副本,不会出现多线程冲突:
#include <iostream> #include <sys/types.h> #include <sys/stat.h> #include <ftw.h> class Foo { public: int func1(const char *fpath, const struct stat *sb, int typeflag) { total += sb->st_size; std::cout << total << std::endl; return 0; } int func2() { // 把当前实例指针存入线程局部变量 s_threadInstance = this; return ftw("plots", staticCallback, 3); } private: // 静态回调函数,匹配ftw的参数要求 static int staticCallback(const char *fpath, const struct stat *sb, int typeflag) { // 取出线程局部的实例指针,调用成员函数 return s_threadInstance->func1(fpath, sb, typeflag); } int total = 0; // 线程局部静态成员,每个线程拥有独立副本 static thread_local Foo* s_threadInstance; }; // 初始化线程局部变量 thread_local Foo* Foo::s_threadInstance = nullptr;
方案3:全局变量(仅适合单线程单场景)
这个方法最简单,但缺点也很明显——全局变量是进程共享的,如果多个Foo实例同时使用,或者多线程调用,会出现数据混乱,只适合非常简单的测试场景:
#include <iostream> #include <sys/types.h> #include <sys/stat.h> #include <ftw.h> class Foo { public: int func1(const char *fpath, const struct stat *sb, int typeflag) { total += sb->st_size; std::cout << total << std::endl; return 0; } int func2() { // 把当前实例指针存入全局变量 s_globalInstance = this; return ftw("plots", staticCallback, 3); } private: static int staticCallback(const char *fpath, const struct stat *sb, int typeflag) { return s_globalInstance->func1(fpath, sb, typeflag); } int total = 0; static Foo* s_globalInstance; }; // 初始化全局变量 Foo* Foo::s_globalInstance = nullptr;
总结
- 优先用
nftw,它是更现代的接口,支持上下文传递,最优雅安全; - 如果必须用
ftw,选线程局部存储的方案,避免全局变量的线程安全问题; - 全局变量只适合单线程、单实例的简单测试场景,别在生产代码里用。
内容的提问来源于stack exchange,提问作者Miriam Peta
相关产品推荐
相关产品推荐

