2016-03-24 3 views
1

Ich bin neu in Qt und versuche, QThread in einer Konsolenanwendung zu verwenden.Qt: In einer Unterklasse der QThread-Kopie wird der Konstruktor vom Compiler gelöscht

umgebung: Qt Creator 3.6.1; Basierend auf Qt5.6.0 (MSVC2013 32bit); bauen am 14. März 2016; Revision d502727b2c

Was ich getan habe ist:

  1. eine abgeleitete Klasse erstellen QtThread die QThread Klasse erben
  2. einen std Container Vektor erstellen und initialisieren einige Threads
  3. mit std :: for_each alle Thread starten

Hier ist meine Frage

Zuerst im cla ss QtThread Ich habe sonst Copykonstruktor Funktion zu implementieren, werde ich Compiler-Fehler haben

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 

Der Grund Ich habe hier Copykonstruktor zu implementieren, glaube ich, ist die Basisklasse QThread destructor hat ~ QThread(). Der Compiler markiert also copy ctr und verschiebt ctr als delete. Die abgeleitete Klasse erbt copy/move ctr nicht von der Basisklasse.

Drei Fragen dazu.

In der Hauptfunktion verwende ich emplace_back(). Es scheint, dass der Compiler den Kopierkonstruktor statt move verwendet. Warum ~ (der std :: thread ist nur Verschieben, kann nicht kopiert werden, so dass der QThread kopiert werden kann, ist ein bisschen komisch für mich, oder vielleicht habe ich etwas falsch gemacht, aber ich tat es erkennen nicht)

ich nicht Keyword-Standard verwenden, damit der Compiler eine Kopie ctr für mich zu erzeugen, warum

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

der Copykonstruktor ich implementiert ist nicht gut, es erzeuge einfach eine neue Faden und kopiert den Namen der Thread, scheint mir nicht gut, aber ich kann keine bessere Lösung finden. Irgendwelche Vorschläge?

Die Basisklasse QThread hat keinen virtuellen Destruktor. Das scheint mir ungewöhnlich. Das bedeutet, dass die abgeleitete Klasse den Destruktor von QThread nicht implizit aufrufen kann. Oder soll ich QThread überhaupt nicht erben?

Hier ist mein Code, der die QtThread erklärt:

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

Die CPP-Datei

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

Hier ist die Hauptfunktion

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

Vielen Dank für Ihre Zeit, die lange für das Lesen Post und hilft mir :)

[Bearbeiten 1]

Einige experimentelle Code aus der Hauptfunktion entfernt.

Danke für Hyde und cod_fodder machte die Kommentare.

Es gibt ein anderes Detail, was ich mich wundere. Der Compiler fordert mich auf, den Kopierkonstruktor für QtThread zu überlasten (andernfalls löst der Compiler den Fehler CC2280 aus). Aber was ich in der Hauptfunktion versuche, sind Objekte in den Container zu verschieben. Ich weiß, wenn der Verschiebevorgang fehlgeschlagen ist, werden Objekte kopiert. In diesem Fall sollte Q_Object nicht kopiert werden, aber was ist der Grund dafür, dass das QtThread-Objekt nicht verschoben werden kann?

Dank

+9

QObject-Unterklassen können nicht kopiert werden. Denken Sie auch daran, dass QThread kein Thread ist, sondern Thread-Controller. Nur Unterklasse es I Sie möchten ändern, wie Thread gesteuert wird, und denken Sie daran, dass QThread selbst nicht in dem Thread lebt, den es steuert. Das ist sehr wichtig, Detail in Qt, und wenn Sie es nicht verstehen, Unterklasse QThread nicht. – hyde

+0

+1 zu hyde, ich werde weiter ausführen. Was Sie versuchen, ist sehr einfach, ohne jemals von QThread zu erben. Alles, was Sie tun müssen, ist ein Objekt zu erstellen und mit QThread einen neuen Thread zu starten und dann Ihr Objekt hineinzubewegen ... hier ist ein Link zu einer Antwort von früher (ich bin mir sicher, es gibt viele andere) um zu beschreiben, wie dies funktioniert ist fertig: http://stackoverflow.com/questions/36201769/threads-event-loop-in-the-qt-application/36208479#36208479 –

+0

Hallo Hyde, danke für Ihre Kommentare. Hier fand ich einen Artikel über die Unterklasse eines QThreads von Olivier Goffart, einem der ehemaligen Qt-Core-Entwickler: http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html Grundsätzlich ich Ich verwende keine Event-Schleife in der Frage. Also sollte ich QThread hier erben. – r0ng

Antwort

0

Im Blog woboq.com/blog/qthread-you-were-not-doing-so-wrong.html heißt es, dass, wenn Ereignisschleife benötigt wird, wir Arbeiter/Controller-Muster verwenden könnten sonst erbt QThread gut.