使用std::binary_function向量调用transform报错的原因及解决方法
报错原因与解决办法
一、报错原因
你遇到的编译错误核心原因有两个:
std::binary_function的本质:它只是一个仅包含参数和返回值类型定义的空基类,没有重载operator()调用运算符,完全不具备可调用能力。- 对象切片问题:当你把
plus<int>、minus<int>这些继承自std::binary_function的子类对象,存入vector<std::binary_function<int, int, int>>时,子类对象会被"切片"——只保留基类部分的内容,丢失了子类中重载的operator()。
当std::transform尝试调用这个被切片后的基类对象时,找不到对应的operator(),因此报错。
Stack Overflow上的相关回答翻译如下:
std::binary_function仅包含参数和返回值的类型定义,它从设计之初就不是用来作为多态基类的(就算可以,你也会遇到对象切片的问题)。
二、解决办法
推荐两种可行的修复方案:
方案1:使用std::function存储可调用对象
std::function是C++11引入的通用可调用对象包装器,可以兼容所有符合指定签名的函数、函数对象、lambda等,不会出现对象切片问题。
修改后的代码:
#include <algorithm> #include <iostream> #include <vector> #include <functional> // 必须包含该头文件 using namespace std; int main(void) { vector<int> v1 = {1, 2, 10, 23, 13}; vector<int> v2 = {10, 2, 4, -1, 3}; vector<int> result(v1.size()); plus<int> f1; minus<int> f2; multiplies<int> f3; // 将vector的类型改为std::function<int(int, int)> vector<function<int(int, int)>> funcs = {f1, f2, f3}; for (auto& func : funcs) { // 使用引用避免不必要的拷贝 transform(v1.begin(), v1.end(), v2.begin(), result.begin(), func); for (auto value : result) { cout << value << " "; } cout << endl; } return 0; }
方案2:自定义多态基类(繁琐但更灵活)
如果你一定要用多态方式实现,可以自定义一个带纯虚operator()的基类,再用包装器封装原有的函数对象。示例代码:
#include <algorithm> #include <iostream> #include <vector> #include <memory> // 包含智能指针头文件 using namespace std; // 自定义多态基类 struct BinaryFunction { virtual int operator()(int a, int b) const = 0; virtual ~BinaryFunction() = default; // 虚析构避免内存泄漏 }; // 包装器模板,封装各种函数对象 template<typename Func> struct FuncWrapper : BinaryFunction { Func func; FuncWrapper(Func f) : func(f) {} int operator()(int a, int b) const override { return func(a, b); } }; int main(void) { vector<int> v1 = {1, 2, 10, 23, 13}; vector<int> v2 = {10, 2, 4, -1, 3}; vector<int> result(v1.size()); // 使用智能指针存储包装后的对象 vector<unique_ptr<BinaryFunction>> funcs; funcs.emplace_back(make_unique<FuncWrapper<plus<int>>>(plus<int>())); funcs.emplace_back(make_unique<FuncWrapper<minus<int>>>(minus<int>())); funcs.emplace_back(make_unique<FuncWrapper<multiplies<int>>>(multiplies<int>())); for (auto& func_ptr : funcs) { transform(v1.begin(), v1.end(), v2.begin(), result.begin(), *func_ptr); for (auto value : result) { cout << value << " "; } cout << endl; } return 0; }
注意:方案1更简洁高效,是优先推荐的解决方式。
内容的提问来源于stack exchange,提问作者e42d3
相关产品推荐
相关产品推荐

