Ich habe eine Klasse von QObject geerbt:
class Parent: public QObject
{
Q_OBJECT
QObject* cl;
public:
Parent(QObject *parent=0):QObject(parent) {
cl = NULL;
}
QObject* getCl() const {
return cl;
}
void setCl(QObject *obj) {
cl = obj;
}
};
Aber wenn ich schreibe:
Parent ev;
Ich erhalte folgende Fehlermeldung:
main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall Parent::metaObject(void)const " (?metaObject@Parent@@UBEPBUQMetaObject@@XZ)
main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void * __thiscall Parent::qt_metacast(char const *)" (?qt_metacast@Parent@@UAEPAXPBD@Z)
main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual int __thiscall Parent::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@Parent@@UAEHW4Call@QMetaObject@@HPAPAX@Z)
Q_OBJECT
Makro suchen , dann neu erstellen , dann Debug- / Release-Ordner löschen (um alle MOC-Dateien zu löschen) und erneut erstellen. Eines davon sollte helfen.Q_OBJECT
Makros mein Problem behoben hat. Keine Ahnung warum. Aber wenn ich es zurücklege, erhalte ich die gleichen 3 ungelösten Fehler. Ich habe dieses Problem behoben, indem ich die neuen Klassen in die.pro
Datei für QT und die voncmakelists.txt
mir verwendete Datei aufgenommen habe. Nachdem ich den Header und die CPP-Dateien eingefügt hatte, arbeitete der Code mitQObject
.Wenn Sie Visual Studio verwenden, löschen Sie die Zeile
Q_OBJECT
aus der Header-Datei, speichern Sie die Datei, fügen Sie sieQ_OBJECT
wieder in die Header-Datei ein und speichern Sie die Datei erneut. Dies sollte diemoc_*
Datei generieren und korrekt erstellen und verknüpfen.quelle
set(CMAKE_AUTOMOC ON)
public signal:
was er vorher nicht getan hat. Trotzdem habe ich den Linker-Fehler, wannQ_OBJECT
immer er im Code enthalten ist, und einen Laufzeitfehler, der besagt, dass meine benutzerdefinierte Klasse keinen anderen Typ definiert.Ich habe festgestellt, dass einige Antworten auf Visual Studio basieren.
Diese Antwort basiert auf Qt Creator.
Anders als der Name vermuten lässt,
Rebuild Project
wird nicht alles ausgelöscht und von Grund auf neu erstellt. Wenn SieQObject
Ihrer Klasse kürzlich (und / oder Q_OBJECT) hinzugefügt haben, müssen Sieqmake
erneut ausführen , zDies liegt daran, dass standardmäßig
qmake
nur ausgeführt wird, wenn Sie wesentliche Änderungen an Ihrer Lösung vornehmen, z. B. neue Quelldateien hinzufügen oder die.pro
Datei ändern . Wenn Sie Änderungen an einer vorhandenen Datei vornehmen, weiß diese nicht, dass sie ausgeführt werden mussqmake
.Um Qt zu zwingen, alles von Grund auf neu zu erstellen, löschen Sie den Ordner
Debug
oderRelease
.quelle
Das Problem war also, dass ich den Qt MOC-Compiler brauchte, um meine .h-Datei zu kompilieren. Dies ist für alle Klassen erforderlich, die QObject oder eines seiner untergeordneten Elemente erweitern. Das Update umfasste (für mich) das Klicken mit der rechten Maustaste auf die Header-Datei, die Auswahl von Eigenschaften und das Setzen des Elementtyps auf "Qt MOC Input", das Klicken auf "Compile" im Header und das Hinzufügen der resultierenden Datei "moc_myfilename.cpp" zu meiner Projekt.
quelle
Wenn Ihre MOC-Dateien im Visual Studio-Projekt generiert werden, versuchen Sie, sie in das Projekt aufzunehmen, wenn sie nicht im Projekt enthalten sind, und erstellen Sie sie neu.
quelle
Ich hatte das gleiche Problem in Visual Studio und löste es, indem ich die folgenden Schritte ausführte:
Dann in der Custom Build Tool Konfiguration:
Setzen Sie "Command Line" auf:
"$ (QTDIR) \ bin \ moc.exe" "% (FullPath)" -o ". \ GeneratedFiles \ $ (Konfigurationsname) \ moc _% (Dateiname) .cpp" "-fStdAfx.h" "-f ../ ../../src/ filename.h "-DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_NETWORK_LIB -DWIN32_LEAN_AND_MEAN -DDIS_VERSION = 7 -D_MATH_DEFINES_DEFINED "-I. \ SFML_STATIC"" -I . \ GeneratedFiles "" -I. " "-I $ (QTDIR) \ include" "-I. \ GeneratedFiles \ $ (Konfigurationsname)." "-I $ (QTDIR) \ include \ QtCore" "-I $ (QTDIR) \ include \ QtGui" "-I $ (QTDIR) \ include \ QtNetwork"
Stellen Sie "Ausgänge" auf:
. \ GeneratedFiles \ $ (Konfigurationsname) \ moc _% (Dateiname) .cpp
Setzen Sie "Zusätzliche Abhängigkeiten" auf:
$ (QTDIR) \ bin \ moc.exe;% (FullPath)
Ihre genauen Werte können unterschiedlich sein. Sie werden normalerweise über ein Qt-Plugin angewendet.
quelle
Ich verwende CMake zum Verwalten von Qt-Projekten und das neue Q_OBJECT muss unter dem Aufruf QT4_WRAP_CPP hinzugefügt werden. Dadurch wird das moc _ *. Cxx für die Aufnahme in das Projekt generiert und die ungelösten externen Elemente werden bereinigt.
quelle
Ich hatte dieses Problem mit Visual Studio 2012, als ich eine Q_OBJECT-Klassendefinition in meiner CPP-Datei hatte. Durch Verschieben der Klassendefinition in die Headerdatei wurde das Problem behoben.
Es sieht so aus, als ob es möglich sein sollte, die Q_OBJECT-Klasse in einer CPP-Datei zu unterstützen, indem die CPP-Datei zu moc hinzugefügt wird, aber ich habe dies nicht versucht.
quelle
Ich habe meinem Projekt manuell CPP / UI-Dateien hinzugefügt, aber vergessen, die Header-Datei explizit als Header-Datei hinzuzufügen. Beim Kompilieren wurde eine ähnliche Fehlermeldung wie oben angezeigt, und die Datei moc _ *. Cpp wurde nicht im Debug- (oder Release-) Verzeichnis des Builds generiert. Das war kein so offensichtlicher Fehler, qmake hat sich nicht beschwert und außer der Linker-Nachricht habe ich keine Fehler bekommen.
Wenn also jemand erneut auf dasselbe Problem stößt (oder denselben Fehler beim Kopieren und Verschieben macht): Stellen Sie sicher, dass die Header-Dateien auch zu Ihrer Projektdatei hinzugefügt wurden
quelle
Mein Problem war, dass eine meiner Dateien, die ein Qt-Makro verwendeten, nicht zugeordnet wurde. Ich habe herausgefunden, dass das Qt-Plugin für Visual Studio das
Q_NAMESPACE
Makro nicht erkennt und daher die Datei nicht zur Zuordnungsliste hinzufügt.Also habe ich die Lösung aus dieser Antwort verwendet , um die Datei zur Mikrofonliste hinzuzufügen:
Seien Sie vorsichtig mit den verschiedenen Optionen für
Debug
undRelease
-Modus.Bauen Sie es jeweils einmal in
Debug
undRelease
-ModusJetzt sollte "moc_filename.cpp" in
Generated Files\Debug
und seinGenerated Files\Release
.Klicken Sie mit der rechten Maustaste auf die einzelnen Elemente und ändern Sie die Eigenschaften:
Debug
: Konfiguration ändern inRelease
und dann ändernGeneral->Excluded from build
inyes
.Release
: Konfiguration ändern inDebug
und dann ändernGeneral->Excluded from build
inyes
.quelle
In meinem Fall (mit QtAdd-in mit VS2012 und Qt v4.8.4) hat keiner der oben genannten Vorschläge funktioniert. Aus irgendeinem Grund konnte VS keine richtigen MOC-Dateien generieren (Build-Ausgabe: Keine relevanten Klassen gefunden. Keine Ausgabe generiert.) Und als ich relevante Header von Hand kompilierte (qt moc als Compiler festlegen und auf 'Kompilieren' klicken), erzeugte es eine leere Moc-Datei .
Es funktionierte, alle erforderlichen Mocs über die Befehlszeile (moc -o moc_SomeClass.cpp SomeClass.h) zu kompilieren und dann die falschen im Ordner GeneratedFiles zu ersetzen.
Dies ist nur eine Problemumgehung (und keine praktische für ein großes Projekt), um Ihr Projekt erfolgreich zu erstellen, erklärt jedoch nicht wirklich das seltsame VS / QtAdd-In-Verhalten.
quelle
Mit QtAdd-in mit VS2010 wurde mir klar, dass die moc _ *. Cpp-Dateien im Ordner GeneratedFiles / Debug aktualisiert wurden, obwohl ich mich im Release-Modus befand. Das Kopieren der Dateien in den Release-Ordner hat bei mir funktioniert.
quelle
Ich habe dieses Problem bei der Verwendung einer "privaten Klasse" in Qt festgestellt, wenn das Programmiermuster " PIMPL " (private Implementierung) verwendet wurde. Qt verwendet dieses Modell im gesamten Quellcode. Ich habe es selbst wirklich gemocht.
Diese Technik beinhaltet die Verwendung einer "privaten" vorwärts deklarierten Klasse in einer öffentlichen Header-Datei, die von der "öffentlichen" Klasse verwendet wird (dh sie ist "übergeordnet"). Das übergeordnete Element verfügt dann über einen Zeiger auf eine Instanz der privaten Klasse als Datenelement.
Die "private" Klasse wird vollständig in der cpp-Datei für die öffentliche Klasse definiert. Es gibt KEINE Header-Datei für die private Klasse.
Die ganze "Drecksarbeit" wird mit dieser Privatklasse erledigt. Dies verbirgt normalerweise die gesamte Implementierung Ihrer öffentlichen Klasse, einschließlich aller anderen privaten Mitglieder (sowohl Daten als auch Funktionen).
Ich empfehle dringend, sich mit dem PIMPL-Muster vertraut zu machen - insbesondere, wenn Sie jemals die interne Qt-Quelle lesen werden.
Ohne diesen Codierungsstil weiter zu erläutern, ist hier der Punkt, der sich auf diese Frage bezieht ... Damit das
Q_OBJECT
Makro innerhalb der cpp für die "private" Klasse QObject funktioniert, die Signale / Slot usw. verwenden kann, mussten Sie dies explizit tun Fügen Sie die .moc zur öffentlichen Klasse in die cpp ein :#include "MyPublicClass.moc"
Sie können alle IDE-Warnungen zu dieser Zeile ignorieren.
Ich bin mir nicht sicher, ob es genau auf den Punkt kommt, aber diese Aufnahme sehe ich immer NACH der Definition der privaten Klasse und nicht oben auf dem CPP (wie Includes normalerweise platziert werden). Das cpp-Layout sieht also folgendermaßen aus:
quelle
Visual Studio 2017.
Ich habe eine Datei hinzugefügt, um das Qt-Projekt bereits einzurichten, und habe diesen Fehler erhalten. Wie ich es behoben habe:
Klicken Sie mit der rechten Maustaste auf die Kopfzeile in den Eigenschaften des Projektmappen-Explorers ... -> Konfigurationseigenschaften -> Allgemein -> Elementtyp Änderung von C / C ++ - Kopfzeile zu Qt Meta-Object Compiler (moc)
voila :)
quelle
Dies ist mir kürzlich beim Wechsel von MingW zu MSVC passiert. Ich hatte eine prototypisierte Klasse / Struktur als Klasse aufgeführt, und MingW hatte nichts dagegen.
MSVC sieht definitiv einen Unterschied zwischen
class
undstruct
wenn es um Prototyping geht.Hoffe, das hilft eines Tages jemand anderem.
quelle
In meinem Fall hat keines der oben genannten Verfahren funktioniert, aber es war völlig mein Fehler.
Ich hatte virtuelle Funktionen in der .h-Datei überschrieben (deklariert), sie aber nie in .cpp definiert :)
quelle
Ich habe mein Problem gelöst, indem ich dies zu meiner Header-Datei hinzugefügt habe:
#ifndef MYCLASSNAME_H #define MYCLASSNAME_H ... // all the header file content. #endif
quelle
Beide Antworten funktionieren für mich in der VS 2013-Umgebung. Ich löse das Problem schließlich, indem ich die .h / .cpp aus dem Projekt entferne und wieder hinzufüge.
quelle
Ich arbeite in VS2015 mit einem integrierten Perforce p4v-Client. In meinem Fall hat Perforce versucht, einem Depo eine MOC-Datei hinzuzufügen. Als ich diesen Vorgang zurückgesetzt habe, hat Perforce diese MOC-Datei aus dem Projekt entfernt und gelöscht. Die Datei wurde nach der nächsten Kompilierung neu erstellt, war aber nicht im Projekt enthalten. Ich muss sie manuell zu den generierten Dateien hinzufügen, als ich endlich verstanden habe, wo das Problem lag.
quelle
Ich habe das gleiche Problem, meine Lösung war die Codierung (meine Datei mit "UTF16LE BOM" kann nicht mit moc.exe generiert werden), ich erstelle eine andere Datei mit ASCII-Codierung und es funktioniert.
HxD HexEditor kann Ihnen helfen, die Kodifizierung zu sehen.
quelle
Ich weiß, dass dies eine sehr alte Frage ist, aber sie scheint immer noch interessant zu sein (ich war in den letzten Monaten mindestens 4 oder 5 Mal hier) und ich habe anscheinend einen anderen Grund gefunden, aus dem dieser Fehler auftreten kann.
In meinem Fall in der Header-Datei habe ich falsch eingegeben:
#include "MyClass.h""
Erst nachdem ich die gesamte Ausgabe überprüft hatte, stellte ich fest, dass der Compiler in dieser Zeile eine Warnung ausgab.
Nachdem ich das zusätzliche Anführungszeichen entfernt habe, wird mein QObject perfekt kompiliert!
quelle
Für mich ist dies die Ursache: Einige Header- oder Quelldateien sind nicht in der QT-Projektdatei enthalten
quelle
Konfrontiert mit diesem Problem bei verketteten CMake-Zielen. Es stellte sich heraus, dass ich
CMAKE_AUTOMOC
auch in Zielen aktivieren musste, die Qt nicht direkt (transitiv) verwendeten. Es stellte sich auch heraus, dassCMAKE_AUTOMOC
dies nicht ohnefind_package(QtX)
dasselbeCMakeLists.txt
oderCMakeLists.txt
übergeordnetes Element verwendet werden kann.quelle