函数指针静态初始化:类静态实例的函数指针语法问题
解决静态初始化带函数指针的类实例问题
首先得指出你当前写法的核心问题:你试图用lambda访问类的非静态成员theToken,但bool (*theDefault)(void)这种普通函数指针没有办法关联到具体的类实例,也不能捕获实例的成员变量——无捕获的lambda可以转换为普通函数指针,但一旦你在lambda里引用theToken,要么编译报错(因为找不到this指针),要么这个lambda变成捕获型,无法转换成普通函数指针。
下面给你几种可行的解决方案,根据你的实际需求选择:
方案一:修改函数指针类型,传递实例指针
这是最符合你需求的方案,让函数指针接受一个fooClass*参数,这样就能在函数里访问对应实例的theToken:
首先修改类定义:
#include <string> using namespace std; class fooClass { public: // 注意要把成员设为public,否则静态初始化无法访问 int theToken; string theOutput; bool (*theDefault)(fooClass*); // 调整函数指针,接受实例指针 };
然后你可以用普通函数或者无捕获lambda来初始化:
用普通函数的写法:
// 定义匹配的函数 bool checkToken(fooClass* instance) { return (instance->theToken & 1) ? true : false; } // 静态初始化实例 fooClass test { 1, "Welcome", checkToken };
用无捕获lambda的写法(C++11及以上支持):
fooClass test { 1, "Welcome", [](fooClass* instance) { return (instance->theToken & 1) ? true : false; } };
调用这个函数指针的时候,需要传入实例本身:
test.theDefault(&test); // 会返回true,因为test.theToken是1
方案二:使用成员函数指针
如果不想修改函数指针的参数,可以改用类的成员函数指针,这样函数可以直接访问当前实例的成员:
修改类定义:
class fooClass { public: int theToken; string theOutput; bool (fooClass::*theDefault)(void); // 成员函数指针类型 // 定义成员函数 bool checkToken() { return (theToken & 1) ? true : false; } };
静态初始化实例时,直接指定成员函数的地址:
fooClass test { 1, "Welcome", &fooClass::checkToken };
调用的时候需要用成员函数指针的语法:
(test.*test.theDefault)(); // 注意括号不能少,返回true
方案三:改用静态成员(不推荐,除非所有实例共享状态)
如果把theToken改成静态成员,普通函数指针就能访问它,但这样所有fooClass实例的theToken是同一个值,可能不符合你的多实例需求:
class fooClass { public: static int theToken; // 静态成员 string theOutput; bool (*theDefault)(void); }; // 初始化静态成员 int fooClass::theToken = 1; // 定义匹配的函数 bool checkToken() { return (fooClass::theToken & 1) ? true : false; } // 静态初始化实例 fooClass test { 1, "Welcome", checkToken };
关键总结
- 普通无参函数指针无法直接访问类的非静态成员,因为没有隐含的
this指针; - 无捕获lambda可以转换为普通函数指针,但捕获了变量的lambda不行;
- 如果你需要每个实例的函数指针访问自己的成员,方案一或方案二是更合理的选择。
内容的提问来源于stack exchange,提问作者Striding Dragon
相关产品推荐
相关产品推荐

