C++17如何将同签名非静态类成员函数存入vector并依次执行
错误原因
非静态成员函数调用时依赖具体的类对象实例,它隐含第一个入参为当前类的this指针,你直接传递Test::Func的实际签名为int(Test*, const string&, int),和你定义的std::function<int(const string&, int)>签名不匹配,因此编译报错。同时注意取非静态成员函数地址时需要加&符号。
C++17下的实现方案
推荐两种常用实现方式,均可以满足将多个同签名成员函数存入vector批量调用的需求:
方案1:用Lambda捕获当前实例(更推荐,可读性更高)
直接在Lambda中捕获this指针,内部调用对应成员函数即可,语法简洁没有多余的占位符:
#include <iostream> #include <vector> #include <functional> #include <string> using namespace std; class Test { int Func1(const string& input, int index) { cout << "Func1 called, input: " << input << ", index: " << index << endl; return 1; } int Func2(const string& input, int index) { cout << "Func2 called, input: " << input << ", index: " << index << endl; return 2; } public: void Execute() { vector<function<int(const string&, int)>> exes; // 存入多个同签名成员函数 exes.push_back([this](const string& input, int index) { return Func1(input, index); }); exes.push_back([this](const string& input, int index) { return Func2(input, index); }); // 批量逐个调用 for (auto& func : exes) { int res = func("test string", 10); cout << "call result: " << res << endl; } } }; int main() { Test test; test.Execute(); cout << "Hello World!" << endl; return 0; }
方案2:用std::bind绑定实例
通过std::bind将当前实例指针绑定到成员函数的第一个隐含入参位置,用占位符对应剩余的参数:
// Execute函数部分修改为如下即可 void Execute() { using namespace std::placeholders; vector<function<int(const string&, int)>> exes; exes.push_back(std::bind(&Test::Func1, this, _1, _2)); exes.push_back(std::bind(&Test::Func2, this, _1, _2)); // 调用方式和方案1完全一致 for (auto& func : exes) { int res = func("test string", 10); cout << "call result: " << res << endl; } }
扩展说明
如果需要存入不同Test实例的成员函数,可以将std::function的签名定义为function<int(Test*, const string&, int)>,存入时直接存成员函数地址,调用时传入对应实例指针即可:
vector<function<int(Test*, const string&, int)>> exes; exes.push_back(&Test::Func1); exes.push_back(&Test::Func2); // 调用时传入实例指针 Test t1, t2; exes[0](&t1, "input1", 1); exes[1](&t2, "input2", 2);
内容的提问来源于stack exchange,提问作者Donotalo
相关产品推荐
相关产品推荐

