You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 07:35:22