Qt:在QThread-copy的一个子类中,构造函数被编译器删除

Qt: in a sub-class of QThread copy, the constructor is deleted by compiler

本文关键字:子类 构造函数 删除 编译器 一个 QThread-copy Qt      更新时间:2023-10-16

我是Qt的新手,正在尝试在控制台应用程序中使用QThread。

环境:Qt创建者3.6.1;基于Qt5.6.0(MSVC2013 32位);2016年3月14日建造;修订版d502727b2c

我所做的是:

  1. 创建派生类QtThread继承QThread类
  2. 创建一个std容器向量并初始化几个线程
  3. 使用std::for_each启动所有线程

这是我的问题

首先,在类QtThread中,我必须实现复制构造函数,否则,我将出现编译错误

 C:Program Files (x86)Microsoft Visual Studio 14.0VCincludexmemory0:657: error: C2280: 'QtThread::QtThread(const QtThread &)': attempting to reference a deleted function

我认为,我必须在这里实现复制构造函数的原因是基类QThread具有析构函数~QThread()。因此编译器会将复制ctr和移动ctr标记为删除。派生类没有从基类继承复制/移动ctr。

与此相关的三个问题。

在主函数中,我使用template_back()。编译器似乎使用了复制构造函数而不是move。为什么~(std::线程只移动,无法复制,所以QThread可以复制对我来说有点奇怪,或者可能我做错了什么,但我没有意识到)

我不能使用关键字default让编译器为我生成一个副本ctr,为什么

QtThread(const QtThread &in_thread) = default; // not working, still having compile error C2280

我实现的复制构造函数不好,它只是创建另一个线程并复制线程的名称,对我来说似乎不好,但我找不到更好的解决方案。有什么建议吗?

基类QThread没有虚拟析构函数。这在我看来很不寻常。这意味着派生类不能隐式调用QThread的析构函数。或者我根本不应该继承QThread?

以下是我声明QtThread:的代码

#pragma once
#include <QtCore>
#include <QDebug>
#define qtout qDebug()
class QtThread : public QThread
class QtThread : public QThread
{
    Q_OBJECT
public:
    QtThread():QThread(nullptr){}
    explicit QtThread(const QString &in_name);
    // This copy constructor create a different thread with same name, bad
    QtThread(const QtThread &in_thread) : QThread() { m_name = in_thread.m_name;} // have to implement copy constructor otherwise, the code will have error: C2280 compile error
    //error: C2280: 'QtThread::QtThread(const QtThread &)': attempting to reference a deleted function
    //QtThread(const QtThread &in_thread) = default;
    void run();
    QString m_name;
};

cpp文件

#include "qtthread.h"
QtThread::QtThread(const QString &in_name)
    : QThread()
    , m_name(in_name)
{}
void QtThread::run()
{
    qtout << "QtThread" << m_name << "start to run";
    for(int i = 0; i<1000; i++)
        qtout << m_name << ": " << i;
}

这是的主要功能

#include <QCoreApplication>
#include "qtthread.h"
#include <vector>
#include <algorithm>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    std::vector<QtThread> ts;
    ts.emplace_back(QtThread("Tx"));
    ts.emplace_back(QtThread("T5"));
    ts.emplace_back(QtThread("T6"));
    std::for_each(ts.begin(), ts.end(), [](QtThread &t){t.start();});
    return a.exec();
}

感谢您花时间阅读长文并帮助我:)

[编辑1]

从主函数中删除了一些实验代码。

感谢hyde和cod_adder的评论。

还有一个细节我想知道。编译器要求我重载QtThread的复制构造函数(否则编译器会抛出错误CC2280)。但是我在主函数中要做的是将对象移动到容器中。我知道当移动操作失败时,对象将被复制。在这种情况下,不应该复制Q_Object,但是是什么原因导致QtThread对象无法移动?

感谢

在博客woboq.com/blog/qthread-you-were-not-doing-so-wrong.html中,声明当需要事件循环时,我们可以使用worker/controller模式,否则继承qthread就好了。