C++将lambda作为类参数存储时触发std::bad_function_call异常如何解决
问题原因
你的代码存在3处核心错误,共同导致了std::bad_function_call异常:
- Action构造函数实现缺失类作用域限定
你在类外实现Action的有参构造函数时没有加Action::前缀,相当于只声明了有参构造但没有真正实现,编译器会生成默认构造函数初始化Action对象,不会对成员f做赋值,导致f是空的std::function。 - getAction方法返回类型不匹配
类声明中getAction的返回值是Action类型,但实现时你写成了int,相当于把存储的Action对象强制转为int返回,再调用时拿到的是非法的Action实例,内部的f完全是无效值。 - operator()重载未实现
你只声明了Action的()运算符重载,没有写具体实现,调用时会触发未定义行为。
修复方案
1. 修正Action构造函数与运算符重载实现
给构造函数加上类作用域限定,同时补充()运算符的实现,推荐用初始化列表初始化成员提升效率:
typedef std::function<int(int)> func; struct Action { Action(func); int operator()(int x); func f; }; // 加类作用域限定,用初始化列表赋值 Action::Action(func f) : f(std::move(f)) {} // 实现运算符重载 int Action::operator()(int x) { return f(x); }
2. 修正Learning类的getAction实现
把返回值类型改回Action,可选择增加边界检查避免数组越界:
class Learning { public: void addAction(Action); Action getAction(int idx); private: std::vector<Action> actions; }; void Learning::addAction(Action act) { actions.push_back(act); } // 修正返回值类型为Action Action Learning::getAction(int idx) { if (idx < 0 || idx >= actions.size()) { throw std::out_of_range("索引超出actions范围"); } return actions[idx]; }
3. 可选逻辑优化
你当前lambda用的是后置自增y++,返回的是自增前的原值,运行后会输出0,如果需要返回自增后的值可以改成前置自增++y。
修复后完整运行代码
#include <iostream> #include <functional> #include <vector> #include <stdexcept> typedef std::function<int(int)> func; struct Action { Action(func); int operator()(int x); func f; }; Action::Action(func f) : f(std::move(f)) {} int Action::operator()(int x) { return f(x); } class Learning { public: void addAction(Action); Action getAction(int idx); private: std::vector<Action> actions; }; void Learning::addAction(Action act) { actions.push_back(act); } Action Learning::getAction(int idx) { if (idx < 0 || idx >= actions.size()) { throw std::out_of_range("索引超出范围"); } return actions[idx]; } int main(){ Learning robot; robot.addAction(Action([](int y) ->int{return ++y; })); std::cout << robot.getAction(0)(0) << std::endl; // 输出1 return 0; }
内容的提问来源于stack exchange,提问作者Zain Ahmed
相关产品推荐
相关产品推荐

