2017-01-12 3 views
3

Ich arbeite mit Qt 5.7 (C++).Definieren Sie eine QObject-abgeleitete Klasse in einem anonymen Namespace?

Innerhalb der cpp-Datei einer Klasse verwende ich einen anonymen Namespace, um eine Klasse (ein Dienstprogramm) zu erstellen, die ich nur in dieser Datei verwenden werde.

Allerdings habe ich Linking Fehler, wenn die Dienstprogramm-Klasse von einer Qt-Klasse abgeleitet ist. Ich denke, dass das Problem am Makro Q_OBJECT liegt, wenn ich es nicht hinzufüge, bekomme ich die Fehler nicht. Aber in jeder von Qt abgeleiteten Klasse ist es zwingend erforderlich, das Makro Q_OBJECT zu verwenden.

Wie kann ich diesen Fehler vermeiden? Gibt es einen anderen Ansatz, um eine Dienstprogrammklasse mit Dateibereich zu haben?

Einfaches Beispiel zum Anzeigen von Fehlern: Die Klasse CMyClass verwendet eine Dienstprogrammklasse (mit dem Namen CUtility), die von QWidget abgeleitet wird.

Vielen Dank.

CMyClass.h

class CMyClass 
{ 
public: 
    CMyClass(); 
    void someMethod(); 
}; 

CMyClass.cpp

#include <QtWidgets> 
#include "CMyClass.h" 

namespace 
{ 
    class CUtility : public QWidget 
    { 
     Q_OBJECT 
    public: 
     CUtility(QWidget *p_parent = 0) : QWidget(p_parent){qDebug() << "CUtility constructor";} 
     void utilityMethod() {qDebug() << "This is CUtility::utilityMethod()";} 
    }; 
} 


CMyClass::CMyClass() 
{ 
    qDebug() << "CMyClass constructor."; 
} 

void CMyClass::someMethod() 
{ 
    qDebug() << "This is CMyClass::someMethod()."; 
    CUtility p_myUtil; 
    p_myUtil.utilityMethod(); 
} 

Die Fehler sind:

LNK2001: extern Symbol „public: virtual Struktur QMetaObject const * __cdecl 'anonymer Namespace' :: CUtility :: metaObject (void) const "(? metaObject @ CUtility ? @ A0x27a8253c @@ UEBAPEBUQMetaObject @@ XZ)

LNK2001: extern Symbol? "Public: virtual void * __cdecl` anonymen Namespace ':: CUtility :: qt_metacast (char const *)"(qt_metacast @ CUtility @ A0x27a8253c @@ UEAAPEAXPEBD @ Z) sin Resolver

LNK2001: extern Symbol "public: virtual int __cdecl` anonymen Namespace ':: CUtility :: qt_metacall (enum QMetaObject :: Anruf, int, void * *)"? (qt_metacall @ CUtility @? A0x27a8253c @@ UEAAHW4Call @ QMetaObject @@ HPEAPEAX @ Z) sin Resolver

+1

Haben Sie am Ende von CMyClass.cpp das übliche '#include" CMyClass.moc "versucht und dann qmake + make erneut ausgeführt? – peppe

Antwort

3

es mit dem Q_OBJECT Makro funktioniert nicht, weil die Makro-Mitglieder zu Ihrer Klasse hinzufügen, die Mitglieder, die in der C++ Code definiert werden durch der Moc (in der Regel in moc_CMyClass.cpp macht es inkompatibel mit einem Datei-Bereich). Außerdem befindet sich in Ihrem Fall die Q_OBJECT in einer cpp-Datei und wird von qmake und dem moc nicht berücksichtigt (was bedeutet, dass moc_CMyClass.cpp nicht generiert wird oder einige Funktionen fehlen).

Eine Lösung ist, das Q_OBJECT Makro zu überspringen, es ist nicht obligatorisch und Sie brauchen es möglicherweise nicht. Der Nachteil ist, dass Sie Introspektionsinformationen über Ihre Klasse verlieren und keine Signale und Slots deklarieren können.

+0

Danke. Wenn ich jedoch dieselbe Dienstklasse haben möchte, wie kann ich den Umfang begrenzen? Ich meine, meine Klasse CUtility wird nur von CMyClass verwendet, und ich möchte kein weiteres Dateipaar erzeugen. Wenn es nur eine Funktion wäre, würde ich eine statische Funktion verwenden, aber das ist mit einer Klasse nicht möglich. Irgendwelche Vorschläge? –

+0

Wenn Sie das Makro 'Q_OBJECT' haben MÜSSEN, müssen Sie Ihre Klasse in einer '.h' Datei definieren. Sobald es in einer Header-Datei ist, können Sie nicht wirklich verhindern, dass eine andere Datei es aufnimmt und die dort definierte Klasse verwendet. –

Verwandte Themen