it-swarm.com.de

Nicht aufgelöstes externes Symbol "public: virtual struct QMetaObject const * __thiscall Parent

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 " ([email protected]@@[email protected]@XZ)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void * __thiscall Parent::qt_metacast(char const *)" ([email protected]@@[email protected])

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual int __thiscall Parent::qt_metacall(enum QMetaObject::Call,int,void * *)" ([email protected]@@[email protected]@@[email protected])
58

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

64

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

53
MPicazo

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

Diese Antwort basiert auf Qt Creator.

Anders als der Name andeutet, Rebuild Project wird nicht alles wegwischen und von Grund auf neu erstellen. Wenn Sie kürzlich QObject (und/oder Q_OBJECT) zu Ihrer Klasse hinzugefügt haben, müssen Sie qmake erneut ausführen, z.

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

Dies liegt daran, dass qmake standardmäßig nur dann 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 eine vorhandene Datei bearbeiten, weiß sie nicht, dass sie qmake ausführen muss.

Löschen Sie den Ordner Debug oder Release.

27
Stephen Quan

Das Problem war also, ich brauchte den Qt MOC-Compiler, um meine .h-Datei zu kompilieren. Dies ist für alle Klassen erforderlich, die QObject oder eines seiner untergeordneten Elemente erweitern. Der Fix beinhaltete (für mich) einen Rechtsklick auf die Header-Datei, das Auswählen von Eigenschaften und das Festlegen des Elementtyps auf "Qt MOC-Eingabe", das Klicken auf "Compile" im Header und das Hinzufügen der resultierenden Datei moc_myfilename.cpp zu my Projekt.

8
Vern Jensen

Wenn Ihre Moc-Dateien im Visual Studio-Projekt generiert werden, versuchen Sie, sie in das Projekt aufzunehmen, wenn sie nicht in das Projekt aufgenommen werden.

7
Akın Yılmaz

Ich hatte das gleiche Problem in Visual Studio und konnte es mit den folgenden Schritten beheben: 

  1. Klicken Sie im Lösungs-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. setze "Kommandozeile" 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\$ (ConfigurationName). " "-I $ (QTDIR)\include\QtCore" "-I $ (QTDIR)\include\QtGui" -I $ (QTDIR)\include\QtNetwork "

  3. setze "Ausgänge" auf: 

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

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

6
Trevor Hickey

Ich verwende CMake zur Verwaltung von Qt-Projekten, und der 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 nicht aufgelösten externen Elemente bereinigt.

4
whatnick

Ich hatte dieses Problem mit Visual Studio 2012, als ich eine Q_OBJECT-Klassendefinition in meiner cpp-Datei hatte. Durch das Verschieben der Klassendefinition in die Headerdatei wurde das Problem behoben.

Es scheint, dass es möglich sein sollte, die Q_OBJECT-Klasse in der cpp-Datei zu unterstützen, indem die cpp-Datei zu moc hinzugefügt wird. Ich habe dies jedoch nicht versucht.

3
Edward

Ich habe manuell cpp/ui-Dateien zu meinem Projekt hinzugefügt, habe aber vergessen, die Header-Datei explizit als Header-Datei hinzuzufügen. Beim Kompilieren erhielt ich eine ähnliche Fehlermeldung wie oben und die moc _ *. Cpp-Datei (en) wurden nicht im Debug- (oder Release-) Verzeichnis des Builds generiert. Das war kein offensichtlicher Fehler, qmake beschwerte sich nicht und abgesehen von der Linkernachricht bekam ich keine Fehler.

Wenn also wieder jemand auf dasselbe Problem stößt (oder denselben Kopier- und Pase-Fehler macht): Stellen Sie sicher, dass die Header-Dateien auch zu Ihrer Projektdatei hinzugefügt wurden

2

Mein Problem war, dass eine meiner Dateien, die ein Qt-Makro verwendet, nicht moc'ed wurde. Ich habe herausgefunden, dass das Qt Plugin für Visual Studio das Makro Q_NAMESPACE nicht erkennt und die Datei daher nicht zur Moc'ing-Liste hinzufügt.

Also habe ich die Lösung aus dieser Antwort verwendet, um die Datei in die Liste der Mikrofone aufzunehmen:

Sie sollten eine .h-Datei finden, die erfolgreich generiert wurde "moc_ *" und kopieren Sie den gesamten Inhalt in "Custom Build Tool -> General" zur neuen .h-Datei-Einstellungsseite.

Seien Sie vorsichtig mit den verschiedenen Optionen für Debug und Release- Mode.

Bauen Sie danach Ihr Projekt auf.

Baue es jeweils einmal im Debug und Release- Modus

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

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

Klicken Sie mit der rechten Maustaste auf jeden von ihnen und ändern Sie die Eigenschaften:

  • Die Datei in Debug: Ändern Sie die Konfiguration in Release und ändern Sie dann General->Excluded from build in yes.
  • Die Datei in Release: Ändern Sie die Konfiguration in Debug und ändern Sie dann General->Excluded from build in yes.
1
Darkproduct

In meinem Fall (bei Verwendung von QtAdd-in mit VS2012 und Qt v4.8.4) funktionierte keiner der oben genannten Vorschläge. Aus irgendeinem Grund konnte VS keine richtigen Moc-Dateien erstellen (Build-Ausgabe: Keine relevanten Klassen gefunden. Keine Ausgabe generiert.) und als ich die relevanten Header manuell kompilierte (qt moc als Compiler setzen und auf 'Compile' klicken), wurde eine leere Moc-Datei erstellt. 

Die Arbeit bestand darin, alle erforderlichen Mocs von der Befehlszeile aus zu kompilieren (moc -o moc_SomeClass.cpp SomeClass.h) und dann die falschen im Ordner GeneratedFiles zu ersetzen.

Dies ist nur eine Problemumgehung (und keine praktische Lösung für ein großes Projekt), damit Ihr Projekt erfolgreich erstellt werden kann, erklärt jedoch nicht wirklich das seltsame Verhalten von VS/QtAdd-in.

1
dianull

Als ich QtAdd-in mit VS2010 verwendete, wurde mir klar, dass die Moc _ *. Cpp-Dateien im Ordner GeneratedFiles/Debug aktualisiert wurden, obwohl ich im Freigabemodus war. Das Kopieren der Dateien in den Release-Ordner hat für mich funktioniert.

1
zengaja

Dieses Problem ist bei der Verwendung einer "privaten Klasse" in Qt aufgetreten, wenn das Programmiermuster "PIMPL" (private Implementierung) verwendet wird. Qt verwendet dieses Modell im gesamten Quellcode. Ich habe es selbst sehr gerne gemacht. 

Diese Technik beinhaltet die Verwendung einer "privaten" vorwärts deklarierten Klasse in einer öffentlichen Header-Datei, die von der "öffentlichen" Klasse verwendet wird (d. H. Es ist "Eltern"). Das übergeordnete Element verfügt dann über einen Zeiger auf eine Instanz der privaten Klasse als Datenmitglied.

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. 

Alle "schmutzigen Arbeiten" werden 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, etwas über das PIMPL-Muster zu lernen - insbesondere, wenn Sie jemals die interne Qt-Quelle lesen. 

Ohne diesen Codierstil näher zu erläutern, ist hier der Punkt, der sich auf diese Frage bezieht ... Damit das Q_OBJECT-Makro innerhalb des cpp für die "private" -Klasse zum QObject wird, das Signale/Steckplatz usw. verwenden kann, you erforderlich, um die .moc-Klasse explizit in die öffentliche Klasse in der cpp aufzunehmen:

#include "MyPublicClass.moc"

Sie können alle IDE - Warnungen zu dieser Zeile ignorieren.

Ich bin mir nicht sicher, ob das genau von Belang ist, aber diese Einbeziehung sehe ich immer NACH der Definition der Privatklasse, anstatt an der Spitze der cpp (wie Einfügungen werden normalerweise platziert). Das CPP-Layout sieht also so aus:

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

Jede Antwort funktioniert 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 es wieder hinzufüge. 

0
Adam Woo

Dies ist mir kürzlich passiert, als ich von MingW zu MSVC wechselte. Ich hatte eine prototypische Klasse/Struktur als Klasse, und MingW hatte nichts dagegen.

MSVC sieht definitiv einen Unterschied zwischen class und struct, wenn es um Prototyping geht.

Hoffe, dass eines Tages jemand anders hilft.

0
phyatt

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

0
Sanbrother

Ich weiß, dass dies eine sehr alte Frage ist, aber es scheint immer noch interessant zu sein (ich war in den letzten Monaten mindestens 4 oder 5 Mal hier) und scheint einen anderen Grund gefunden zu haben, aus dem dieser Fehler möglich ist.

In meinem Fall in der Header-Datei habe ich falsch eingegeben:

#include "MyClass.h""

Erst nachdem ich die gesamte Ausgabe durchgesehen hatte, stellte ich fest, dass der Compiler in dieser Zeile eine Warnung ausgab.

Nun, da ich das zusätzliche Anführungszeichen entfernt habe, kompiliert mein QObject perfekt!

0
Brutus

In meinem Fall funktionierte nichts davon, aber es war mein ganzer Fehler.

Ich hatte virtuelle Funktionen in der .h-Datei überschrieben (deklariert), hatte sie jedoch noch nicht in .cpp definiert :)

0
zar

Ich habe das gleiche Problem, meine Lösung war die Kodierung (meine Datei mit "UTF16LE BOM" kann nicht mit moc.exe generiert werden), Sie erstellen eine andere Datei mit ASCII und das funktioniert.

HxD HexEditor kann Ihnen helfen, die Kodifizierung zu sehen.

0

Ich habe mein Problem gelöst, indem ich es meiner Header-Datei hinzugefügt habe:

#ifndef MYCLASSNAME_H
#define MYCLASSNAME_H

... // all the header file content.

#endif
0
Nadjib Dz

Ich arbeite in VS2015 mit einem integrierten p4v-Client von Perforce ..__ In meinem Fall versuchte Perforce, eine Moc-Datei zu einem Depo hinzuzufügen. Als ich diesen Vorgang rückgängig machte, entfernte Perforce diese Moc-Datei aus dem Projekt und löschte sie . Die Datei wurde nach der nächsten Kompilierung neu erstellt, wurde aber nicht in das Projekt aufgenommen, ich muss sie manuell zu generierten Dateien hinzufügen, als ich endlich wusste, was das Problem war.

0
Flot2011