从类成员函数返回std::function出现编译错误的问题咨询
类成员函数返回std::function编译错误的原因与解决方法
问题现象
当启用代码第4行的#define CLASS 1宏定义时,类testClass的成员函数getFp返回myTestFunction会触发编译错误;但类外部定义的getFp1函数返回普通函数printMessage却能正常运行。
编译错误信息
**Compilation Error** : In member function 'std::function<void(std::__cxx11::basic_string<char>)> testClass::getFp()': Practice.cpp:23:14: error: cannot convert 'testClass::myTestFunction' from type 'void (testClass::)(std::string)' {aka 'void (testClass::)(std::__cxx11::basic_string<char>)'} to type 'std::function<void(std::__cxx11::basic_string<char>)>' 23 | return myTestFunction; | ^~~~~~~~~~~~~~
相关代码
#include <iostream> #include <functional> #include <string> //#define CLASS 1 -------------> Enabling this throws compilation error (?) using namespace std; void printMessage(string str){ cout << str << endl; } void testFunction(std::function<void(std::string)> fp,string s){ fp(s); } #ifdef CLASS class testClass { public : void myTestFunction(std::string s){ cout << s << endl; } public : std::function<void(std::string) > getFp(){ return myTestFunction; } }; #endif std::function<void(std::string) > getFp1(){ return printMessage; } int main(){ std::function<void(string)> fp = printMessage; fp("Whats up !!") ; testFunction(fp,"All is Well"); #ifdef CLASS testClass t ; auto fp1 = t.getFp(); fp1("Calling Private Method ?"); #endif auto fp2 = getFp1(); fp2("Great !!"); return 0; }
问题原因
不存在从类内函数返回std::function的限制,错误的核心是非静态成员函数和普通函数的本质差异:
- 普通全局函数
printMessage的类型是void(std::string),和std::function<void(std::string)>的签名完全匹配,因此可以直接赋值。 - 类的非静态成员函数
myTestFunction会隐含一个指向类对象的this指针作为第一个参数,它的实际类型是void(testClass::)(std::string),和std::function<void(std::string)>的签名不匹配,所以无法直接转换。
解决方法
方法1:使用std::bind绑定this指针
修改testClass的getFp函数,通过std::bind把当前对象的this指针和成员函数绑定,生成符合签名的可调用对象:
std::function<void(std::string)> getFp(){ return std::bind(&testClass::myTestFunction, this, std::placeholders::_1); }
方法2:使用lambda表达式捕获this
利用lambda捕获当前对象的this指针,在lambda内部调用成员函数,生成匹配签名的可调用对象:
std::function<void(std::string)> getFp(){ return [this](std::string s){ this->myTestFunction(s); }; }
方法3:将成员函数声明为静态函数
如果myTestFunction不需要访问类的非静态成员变量,可以将其声明为静态成员函数,此时它不再隐含this指针,类型与普通全局函数一致:
class testClass { public : static void myTestFunction(std::string s){ cout << s << endl; } public : std::function<void(std::string) > getFp(){ return myTestFunction; } };
内容的提问来源于stack exchange,提问作者Milind
相关产品推荐
相关产品推荐

