1
votes

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

1
QObject subclasses are not copyable. Also, remember that QThread is not thread, it is thread controller. Only subclass it I you want to change how thread is controlled, and remember that QThread itself does not live in the thread it controls. That is very important detail in Qt, and if you don't understand it, don't subclass QThread.hyde
+1 to hyde, I will elaborate further. What you are trying to do is very simple without ever inheriting from QThread. All you need to do is create an object and using QThread startup a new thread and then move your object into it... here is a link to an answer from earlier today (I am sure there are many others) to help describe how this is done: stackoverflow.com/questions/36201769/…code_fodder
Hi hyde, thanks for your comments. Here I found an article talking about subclass of a QThread by Olivier Goffart, one of the former Qt core developers: woboq.com/blog/qthread-you-were-not-doing-so-wrong.html Basically I am not using event loop in the quesiton. So I should inherit QThread here.r0n9

1 Answers

0
votes

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.