Search code examples
c++qtc++11qthread

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


I am new to Qt and trying to use QThread in a console application.

environment: Qt Creator 3.6.1; Based on Qt5.6.0 (MSVC2013 32bit); build on Mar 14 2016; revision d502727b2c

What I did is:

  1. Create a derived class QtThread inherit the QThread class
  2. Create an std container vector and initialize few threads
  3. using std::for_each to start all thread

Here is my question

First, In the class QtThread I have to implement copy constructor function otherwise, I will have compile error

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

The reason I have to implement copy constructor here, I think, is the base class QThread has destructor ~QThread(). So the compiler will mark copy ctr and move ctr as delete. The derived class does not inherit copy/move ctr from base class.

Three issues regarding this.

In the main function, I use emplace_back(). It seems the compiler is using copy constructor instead move.Why~ (the std::thread is move only, unable to be copied, so the QThread can be copied is a bit strange to me, or maybe I did some wrong but I did not realize)

I can not use keyword default to let the compiler generating a copy ctr for me, why

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

The copy constructor I implemented is not good, it just create another thread and copies the name of the thread, seems not good to me, but I cannot find a better solution. Any suggestions?

The base class QThread does not have a virtual destructor. That seems unusual to me. That means derived class can not implicitly call QThread's destructor. Or maybe I am not supposed to inherit QThread at all?

Here is my code that declaring the 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;
};

The cpp file

#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;
}

Here is the main function

#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();
}

Thanks for your time for reading the long post and helping me :)

[Edit 1]

Removed some experimental code from the main function.

Thanks for hyde and cod_fodder made the comments.

There is another detail thing I am wondering. The compiler requires me to overload the copy constructor for QtThread (otherwise compiler throws error CC2280). But what I am trying to do in the main function is move objects into the container. I know when the move operation failed, objects will be copied. In this case, Q_Object is not supposed to be copied, but what is the reason cause the QtThread object unable to be moved?

Thanks


Solution

  • In the blog woboq.com/blog/qthread-you-were-not-doing-so-wrong.html, it states that when event loop is needed, we could use worker/controller pattern, otherwise inherit QThread is good.