Frage

Ist es möglich, der Qt MOC zu sagen, dass ich die Klasse erklären möchte und implementieren sie in einer einzigen Datei statt Spaltung sie in eine .h und CPP-Datei?

War es hilfreich?

Lösung 4

Ich glaube, dies ist der beste Weg zu sein. Es ist eigentlich wie ich jetzt alle meine Objekte konstruieren.

Qt 4.8.7

Works.pro:

SOURCES += \
    main.cpp

HEADERS += \
    Window.h \
    MyWidget.h

main.cpp

#include <QtGui>
#include "Window.h"

int main(int argc, char *argv[])
{
    QApplication app(argc,argv);

    Window window;
    window.show();
    return app.exec();
}

Window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QtGui>
#include "MyWidget.h"

class Window : public QWidget
{
    Q_OBJECT

private:
    MyWidget *whatever;

public:
    Window()
    {
        QHBoxLayout *layout = new QHBoxLayout;
        setLayout(layout);

        whatever = new MyWidget("Screw You");
        layout->addWidget(whatever);

    }
};

#include "moc_Window.cpp"

#endif // WINDOW_H

MyWidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QtGui>

class MyWidget : public QLabel
{
    Q_OBJECT

public:
    MyWidget(QString text) : QLabel(text)
    {
        // Whatever
    }
};

#include "moc_MyWidget.cpp"

#endif // MYWIDGET_H

Erstellen ... qmake Works.pro

make

Andere Tipps

Wenn Sie eine QObject Unterklasse deklarieren und implementieren möchten in Sie CPP-Datei, müssen Sie umfassen manuell die moc-Datei.

Zum Beispiel: (Datei main.cpp)

struct SubObject : QObject
{
    Q_OBJECT
};

//...

#include "main.moc"

Sie müssen erneut ausführen moc (make qmake) nach der #include Anweisung hinzugefügt wird.

TL; DR

Ja, wenn Sie nur über die Dateien im Gespräch, dass Sie selbst schreiben (wie die von moc erzeugte entgegengesetzt). Sie gar nicht zu tun etwas Besonderes benötigen.

Wenn Sie jemals moc Ausgabe explizit in den Dateien aufnehmen möchten Sie schreiben, gibt es einen Fall, in dem Sie muss es tun, und ein Fall, in dem Sie Macht Wunsch es zu tun. Nehmen wir an, dass MyObject Klasse in MyObject.h und Ihre Definition davon erklärt wird, in MyObject.cpp gegeben:

  1. MyObject.moc muss enthalten am Ende von MyObject.cpp iff Sie erklären alle Q_OBJECT Klassen innerhalb MyObject.cpp.

  2. moc_MyObject.cpp können sein eingeschlossen überall in MyObject.cpp die Anzahl der Übersetzungseinheiten in Ihrem Projekt zu halbieren. Es ist eine Build-Zeitoptimierung nur. Wenn Sie es nicht tun, wird moc_MyObject.cpp separat kompiliert werden.

Jedes Mal, wenn Sie hinzufügen oder entfernen Q_OBJECT Makro aus einer beliebigen Quelle oder Headerdatei, oder Sie hinzufügen oder explizite Einschlüsse von moc Ausgabe in solchen Dateien entfernen, müssen Sie erneut ausgeführt Qmake / cmake.

Um re-run Qmake / cmake in Qt Creator, einfach mit der rechten Maustaste auf das Toplevel-Projekt, und wählen Sie Ausführen Qmake oder Ausführen Cmake aus dem Kontextmenü.

Die einfache Antwort

Ein Beispiel qmake-basierte Qt-Projekt von drei Dateien bestehen könnte, wie folgt:

# test.pro
QT       += core
CONFIG   += console
CONFIG   -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
HEADERS += myobject.h

// main.cpp
#include "myobject.h"

int main() {
  MyObject obj;
  obj.staticMetaObject; // refer to a value defined in moc output
  return 0;
}

// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>

class MyObject : public QObject {
   Q_OBJECT
public:
   MyObject() {}
   Q_SLOT void aSlot() {}
};

#endif // MYOBJECT_H

Es ist nicht viel, aber es ist sicherlich gültig. Neben den verschiedenen Bibliotheken, dass das Build-System verbindet unser Projekt mit, gibt es zwei projektspezifische eine Definitionsregel , um genau zu sein, und so ergibt sich eine ungültige C ++ Programm.

Nun könnte man denken, „clever“ zu bekommen und sind gewaltsam die moc Ausgabe in der Header-Datei. Die Qmake / Cmake / QBS werden aufnimmt, und wird dies erkennen und wird nicht separat moc Ausgabe durch den Compiler verarbeitet beliebigemehr, wie Sie es bereits getan haben.

So wird angenommen, dass in dem Projekt oben, Sie myobject.h geändert und lautet wie folgt:

// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>

class MyObject : public QObject {
   Q_OBJECT
public:
   MyObject() {}
   Q_SLOT void aSlot() {}
};

#include "moc_myobject.cpp"
#endif // MYOBJECT_H

Wie es aussieht, wird das Projekt noch kompilieren, scheinbar erfüllen Ihr Ziel nur eine Datei zu haben, die die Gesamtheit der MyObject definiert - die Bits, die Sie geschrieben haben, und die Bits, dass moc erzeugt, beide. Aber es ist nur aufgrund eines unwahrscheinlich glücklichen Umstand: der Inhalt moc_*.cpp ist nach wie vor nur in einer Übersetzungseinheit -

Nehmen wir jetzt an, dass wir eine zweite Quelldatei zu unserem Projekt hinzufügen:

# test.pro
QT       += core
CONFIG   += console
CONFIG   -= app_bundle
TEMPLATE = app
SOURCES += main.cpp test.cpp
HEADERS += myobject.h

// test.cpp
#include "myobject.h"

Nicht viel zu. Es sollte funktionieren, auch wenn es nicht viel tun, nicht wahr?

Ach, es wird nicht verknüpfen. Nun werden die Inhalte von moc_myobject.cpp sind ein Teil von zwei Übersetzungseinheiten. Da moc_myobject.cpp Innenseiten voller Stand-alone-Klasse Mitglied Definitionen sind, verletzt dies die eine Definitionsregel . Die Regel Mandate, dass eigenständige Definitionen nur in eine Übersetzungseinheit innerhalb eines Ziels erscheinen. Der Linker, wobei die Hüter dieser Regel zu Recht beklagt.

Auf Einschließlich moc Ausgabe in der CPP-Datei

Wie angedeutet in der TL; DR., Keiner der oben verbietet ausdrücklich die Aufnahme von moc Ausgabe in Quelle (CPP) Dateien unter bestimmten Umständen

Bei „foo.h“ und „foo.cpp“ und ein Projekt von qmake oder cmake verwalten, wird das Build-System moc direkt auf zwei Ausgänge zur Erzeugung von bis:

  1. moc_foo.cpp von foo.h, iff foo.h enthält Q_OBJECT Makro.

  2. foo.moc von foo.cpp, iff foo.cpp enthält #include "foo.moc".

Lassen Sie uns im Detail untersuchen, warum würden Sie entweder ein in einer CPP-Datei aufgenommen werden sollen.

Einschließlich xxx.moc

Manchmal, vor allem in den Tagen vor der C ++ 11 und Qt 5, kommt es praktisch nur kleine Helfer QObject Klassen für die lokalen Gebrauch innerhalb einer Übersetzungseinheit (Quelldatei) zu erklären.

Dies ist auch praktisch, wenn Single-Datei zu schreiben, in sich geschlossene Testfälle und Beispiele für Stackoverflow Verwendung.

Angenommen, Sie jemand wollte zu zeigen, in einer Datei, wie ein Schlitz von der Ereignisschleife aufgerufen werden:

// main.cpp
#include <QCoreApplication>
#include <QTextStream>
#include <cstdio>

QTextStream out(stdout);

class MyObject : public QObject {
  Q_OBJECT
public:
  MyObject() {}
  Q_SLOT void mySlot() { out << "Hello from " << __FUNCTION__ << endl; }
};

int main(int argc, char ** argv) {
  QCoreApplication app(argc, argv);
  MyObject obj;
  QMetaObject::invokeMethod(&obj, Qt::QueuedConnection, "mySlot");
  QMetaObject::invokeMethod(&app, Qt::QueuedConnection, "quit");
  return app.exec();
}

#include "main.moc"

Da MyObject eine kleine Klasse, die nur lokal in main.moc verwendet wird, wäre es nicht viel Sinn, seine Definition in einem separaten Header-Datei zu setzen. Die #include "main.moc" Linie wird von qmake / cmake bemerkt werden, und main.cpp wird durch moc zugeführt werden, in main.moc führt. Da main.moc definiert Mitglieder MyObject, muss es irgendwo aufgenommen werden, wo MyObject deklariert wird. Da die Erklärung innerhalb main.cpp ist, können Sie keine separate Übersetzungseinheit sein main.moc: es aufgrund MyObject nicht kompiliert werden nicht erklärt zu werden. Der einzige Ort, an dem es deklariert wird, ist innerhalb main.cpp, irgendwo gegen Ende. Deshalb ist es immer eine sichere Wette, gehört foo.moc am Ende foo.cpp.

Eine aufmerksame Leser fragt nun: wie kommt moc_foo.cpp die Deklarationen der Klassen, deren Mitglieder wird es definiert? Ganz einfach: es schließt ausdrücklich die Header-Datei wird erzeugt aus (hier: foo.h). Natürlich foo.moc kann das nicht tun, da sie durch Multiplikation definieren, alles in foo.cpp die einzige Definition Regel brechen würde.

Einschließlich moc_xxx.cpp

Bei besonders großen Qt-Projekten, die Sie haben könnten - im Durchschnitt - zwei Dateien und zwei Übersetzungseinheiten für jede Klasse:

  • MyObject.h und MyObject.cpp sind die Dateien, die Sie schreiben.
  • MyObject.cpp und moc_MyObject.cpp sind die Übersetzungseinheiten.

Es ist möglich, die Anzahl der Übersetzungseinheiten zu halbieren, indem Sie explizit moc_MyObject.cpp irgendwo in MyObject.cpp einschließlich:

// MyObject.cpp
#include "MyObject.h"
#include "moc_MyObject.cpp"
...

Ich glaube, Sie können in der Regel erklären und die Klasse in der Header-Datei zu implementieren, ohne etwas Besonderes, zB:

#include <QObject>

class MyClass : public QObject
{
  Q_OBJECT

  public:
     MyClass(QObject * parent)
     {
        // Constructor Content
     }

     methodExample()
     {
          // Method content
     }
};

Danach Sie die Header-Datei in die pri-Datei hinzufügen und führen Sie qmake wieder und das ist es. Sie haben eine Klasse, die erbt von QObject und umgesetzt wird und int er .h-Datei deklariert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top