C++中使用虚成员函数启动线程的编译错误解决
用std::thread调用多态虚函数时编译错误的解决方法
问题描述
我定义了Base基类以及两个继承自Base的Derived_1和Derived_2派生类,希望通过线程运行派生类中重写的print虚函数,验证会调用哪个版本的函数,但创建std::thread时出现编译错误,该如何解决?
错误原因
编译错误的核心是**std::unique_ptr是不可拷贝的类型**,而std::thread构造函数会尝试拷贝传递的参数。代码中直接把base(std::unique_ptr<Base>对象)作为参数传给std::thread,违反了unique_ptr的移动语义规则,导致编译失败。
另外,原代码遗漏了<memory>头文件,std::unique_ptr和std::make_unique需要该头文件才能正常编译。
解决方案
方法1:用std::move转移unique_ptr所有权
通过std::move将unique_ptr的所有权转移给线程,线程会接管对象的生命周期,虚函数的多态调用依然正常:
std::thread th(&Base::print, std::move(base), std::ref(vec));
方法2:传递原始指针(需保证对象生命周期)
如果不想转移所有权,可以直接获取unique_ptr管理的原始指针传递给线程,注意要确保线程运行期间对象不会被销毁(本示例中main会等待线程结束,所以安全):
std::thread th(&Base::print, base.get(), std::ref(vec));
方法3:使用std::async异步调用
std::async内部会自动处理unique_ptr的移动语义,同样能实现异步调用并等待结果:
auto future = std::async(&Base::print, std::move(base), std::ref(vec)); future.get(); // 等待异步任务完成
修改后的完整代码
#include <string> #include <iostream> #include <thread> #include <vector> #include <memory> // 补充std::unique_ptr所需的头文件 class Base{ public: virtual void print(const std::vector<int> &vec); }; void Base::print(const std::vector<int> &vec){ std::cout << "run Base::print" << std::endl; } class Derived_1: public Base{ public: virtual void print(const std::vector<int> &vec) override; }; void Derived_1::print(const std::vector<int> &vec){ std::cout << "run Derived_1::print" << std::endl; for(int i = 0; i < (vec.size()); i++){ std::cout << vec[i] << " "; } std::cout << std::endl; } class Derived_2: public Base{ public: virtual void print(const std::vector<int> &vec) override; }; void Derived_2::print(const std::vector<int> &vec){ std::cout << "run Derived_2::print" << std::endl; for(int i = 0; i < (vec.size()); i++){ std::cout << vec[i] << " "; } std::cout << std::endl; } int main(){ int classType = 0; std::unique_ptr<Base> base; std::vector<int> vec{0, 1, 2}; if(classType){ base = std::make_unique<Derived_1>(); }else{ base = std::make_unique<Derived_2>(); } // 使用std::move转移unique_ptr所有权 std::thread th(&Base::print, std::move(base), std::ref(vec)); th.join(); return 0; }
更新说明:正如评论指出,不能直接将std::unique_ptr传递给std::thread构造函数,使用std::move转移所有权或std::async均可解决该问题,感谢帮助!
内容的提问来源于stack exchange,提问作者Odirection
相关产品推荐
相关产品推荐

