Nicht aufgelöstes externes Symbol "public: virtuelle Struktur QMetaObject const * __thiscall Parent

72

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)
sayyed mohsen zahraee
quelle

Antworten:

77

Sie sollten den debugOrdner Ihrer Anwendung löschen und erneut ausführen, um dieses Problem zu beheben.

sayyed mohsen zahraee
quelle
7
Ich habe das gleiche Problem. Das Löschen des Debug-Ordners hat nicht geholfen. Noch mehr Ideen?
Vern Jensen
2
@Vern Jensen, nach Q_OBJECTMakro suchen , dann neu erstellen , dann Debug- / Release-Ordner löschen (um alle MOC-Dateien zu löschen) und erneut erstellen. Eines davon sollte helfen.
SpongeBobFan
19
Das Entfernen des Q_OBJECT-Makros aus der Klasse, das Speichern und Hinzufügen von Q_OBJECT funktionierte erneut für mich, wenn ich das QT5-Plugin für VS 2012
Beachwalker
Dies hat auch mein Problem behoben. Aber warum und wie? Jemand bitte erklären. Vielen Dank!
Nayan Soni
5
Ich hatte das gleiche Problem für ein Klassenprojekt. Ich fand, dass das Entfernen des Q_OBJECTMakros 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 .proDatei für QT und die von cmakelists.txtmir verwendete Datei aufgenommen habe. Nachdem ich den Header und die CPP-Dateien eingefügt hatte, arbeitete der Code mit QObject.
Callat
63

Wenn Sie Visual Studio verwenden, löschen Sie die Zeile Q_OBJECTaus der Header-Datei, speichern Sie die Datei, fügen Sie sie Q_OBJECTwieder in die Header-Datei ein und speichern Sie die Datei erneut. Dies sollte die moc_*Datei generieren und korrekt erstellen und verknüpfen.

MPicazo
quelle
3
Keine der anderen Lösungen hat bei mir funktioniert, aber das hat funktioniert! Vielen Dank! ;)
zeFree
4
Wenn Sie CMake verwenden, stellen Sie sicher, dass Sieset(CMAKE_AUTOMOC ON)
Matt
2
Diese Antwort sollte auch als gültige Antwort vermerkt werden!
Adiel Yaacov
2
Woks für mich (VS2017), danke. Kompiliert mit auskommentiertem "Q_OBJECT", wird bei Wiederherstellung nicht kompiliert. Schafft kein Vertrauen in Qt. Ich dachte, das Makro "Q_OBJECT" wäre notwendig?
Pierre
Ich bin auch bei VS 2017. Folgendes passiert für mich: Ich habe AUTOMOC zu meinen CMakeLists hinzugefügt. Das hat meinen Compiler ersticken lassen, public signal:was er vorher nicht getan hat. Trotzdem habe ich den Linker-Fehler, wann Q_OBJECTimmer er im Code enthalten ist, und einen Laufzeitfehler, der besagt, dass meine benutzerdefinierte Klasse keinen anderen Typ definiert.
Starturtle
33

Ich habe festgestellt, dass einige Antworten auf Visual Studio basieren.

Diese Antwort basiert auf Qt Creator.

Anders als der Name vermuten lässt, Rebuild Projectwird nicht alles ausgelöscht und von Grund auf neu erstellt. Wenn Sie QObjectIhrer Klasse kürzlich (und / oder Q_OBJECT) hinzugefügt haben, müssen Sie qmakeerneut ausführen , z

  1. Projekt reinigen
  2. Führen Sie qmake aus
  3. Projekt erstellen

Dies liegt daran, dass standardmäßig qmakenur ausgeführt wird, wenn Sie wesentliche Änderungen an Ihrer Lösung vornehmen, z. B. neue Quelldateien hinzufügen oder die .proDatei ändern . Wenn Sie Änderungen an einer vorhandenen Datei vornehmen, weiß diese nicht, dass sie ausgeführt werden muss qmake.

Um Qt zu zwingen, alles von Grund auf neu zu erstellen, löschen Sie den Ordner Debugoder Release.

Stephen Quan
quelle
1
Brillant! Hat für mich gearbeitet. "Run qmake" ist der Schlüsselschritt. Q_OBJECT ist erforderlich, wenn Sie Slots verwenden möchten.
Pierre
11

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.

Vern Jensen
quelle
Wo genau finden Sie diese "Eigenschaften"? In Qt Creator sehe ich so etwas beim Rechtsklick nicht.
Horst Walter
1
Dies ist in XCode, wenn Sie mit der rechten Maustaste auf die Datei klicken, die in der Ansicht "Navigator" aufgeführt ist (die Liste der Dateien, die Ihr Projekt verwendet).
Vern Jensen
1
Dies ist auch in Visual Studio möglich, aber jemand anderes müsste Ihnen genau sagen, wie Sie es dort konfigurieren sollen. (Ich bin sicher, Sie können die Antwort auf Qts Website finden.)
Vern Jensen
1
Zum Kichern fügte ich eine Header-Datei und eine CPP-Datei hinzu und verschob meine von QtObject abgeleitete Klasse hinein. Dann musste ich auch <QtObject> in die Header-Datei aufnehmen und plötzlich funktionierte es. Diese Dinge sollten wirklich irgendwo dokumentiert werden ...
BitTickler
1
Hat für mich funktioniert, außer dass der Typ "Custom Build Tool" anstelle von "Qt MOC Input" war. Ich benutze Visual Studio 2017.
Captain Normal
7

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.

Akın Yılmaz
quelle
Warum sollte das notwendig sein?
lpapp
Aufgrund einer falschen Konfiguration von VS, die die Verwendung von MOC-Dateien verhindert. Manchmal, selbst wenn es MOC-Dateien korrekt generiert, aber weil sie nicht enthalten sind, verhält es sich so, als ob es nicht existiert
Akın Yılmaz
6

Ich hatte das gleiche Problem in Visual Studio und löste es, indem ich die folgenden Schritte ausführte:

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Header-Datei
  2. Eigenschaften
  3. Ändern Sie "Elementtyp" in "Benutzerdefiniertes Build-Tool".

Dann in der Custom Build Tool Konfiguration:

  1. Gehe zu General
  2. 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"

  3. Stellen Sie "Ausgänge" auf:

    . \ GeneratedFiles \ $ (Konfigurationsname) \ moc _% (Dateiname) .cpp

  4. 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.

Trevor Hickey
quelle
Arbeitete für mich, außer dass ich nach dem ersten Satz von 1,2,3 Schritten aufhören konnte; Die Konfiguration des Custom Build Tools ist vermutlich bereits irgendwo definiert. Ich benutze Visual Studio 2017.
Captain Normal
4

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.

Whatnick
quelle
4

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.

Edward
quelle
1
Das war auch mein Problem. Es ist jedoch ärgerlich, eine interne Klasse in der Header-Datei verfügbar machen zu müssen.
Zitrax
3

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

Vinoj John Hosan
quelle
3

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_NAMESPACEMakro 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:

Sie sollten eine .h-Datei finden, die erfolgreich "moc_ *" generiert hat, und den gesamten Inhalt von "Custom Build Tool -> General" auf die neue Einstellungsseite für die .h-Datei kopieren.

Seien Sie vorsichtig mit den verschiedenen Optionen für Debugund Release-Modus.

Erstellen Sie danach Ihr Projekt.

Bauen Sie es jeweils einmal in Debugund Release-Modus

Fügen Sie abschließend die generierte Datei "moc_ *" zu Ihrem Projekt hinzu.

Jetzt sollte "moc_filename.cpp" in Generated Files\Debugund sein Generated Files\Release.

Klicken Sie mit der rechten Maustaste auf die einzelnen Elemente und ändern Sie die Eigenschaften:

  • Die Datei in Debug: Konfiguration ändern in Releaseund dann ändern General->Excluded from buildin yes.
  • Die Datei in Release: Konfiguration ändern in Debugund dann ändern General->Excluded from buildin yes.
Dunkelprodukt
quelle
Dies ist eine unterschätzte Antwort
Jacob Krieg
1

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.

Dianull
quelle
1

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.

Zengaja
quelle
1

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_OBJECTMakro 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:

  1. "Normale" Includes sind definiert.
  2. Die private Klasse ist definiert.
  3. Der Moc für die öffentliche Klasse ist # enthalten.
  4. Die Implementierung der öffentlichen Klasse ist definiert.
BuvinJ
quelle
1

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 :)

Ashrasmun
quelle
0

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 classund structwenn es um Prototyping geht.

Hoffe, das hilft eines Tages jemand anderem.

Phyatt
quelle
0

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 :)

zar
quelle
0

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
Nadjib Dz
quelle
0

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.

Adam Woo
quelle
0

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.

Flot2011
quelle
0

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.

Jefferson Rondan
quelle
0

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!

Brutus
quelle
0

Für mich ist dies die Ursache: Einige Header- oder Quelldateien sind nicht in der QT-Projektdatei enthalten

Sanbrother
quelle
0

Konfrontiert mit diesem Problem bei verketteten CMake-Zielen. Es stellte sich heraus, dass ich CMAKE_AUTOMOCauch in Zielen aktivieren musste, die Qt nicht direkt (transitiv) verwendeten. Es stellte sich auch heraus, dass CMAKE_AUTOMOCdies nicht ohne find_package(QtX)dasselbe CMakeLists.txtoder CMakeLists.txtübergeordnetes Element verwendet werden kann.

Pugsley
quelle