我正在使用Qt 5.7(C ++)。
在一个类的cpp文件中,我使用一个匿名名称空间来创建一个类(某些实用程序),该类将仅在该文件中使用。
但是,如果实用程序类是从Qt类派生的,则会出现链接错误。我认为问题出在Q_OBJECT宏上,如果我不添加它,我不会得到错误。但是在任何Qt派生类中都必须/建议使用Q_OBJECT宏。
如何避免这种情况? 还有其他方法可以使实用程序类具有文件作用域吗?
显示错误的简单示例:CMyClass类使用从QWidget派生的实用工具类(名为CUtility)。
谢谢。
CMyClass.h
class CMyClass { public: CMyClass(); void someMethod(); };
CMyClass.cpp
#include#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(); }
错误是:
LNK2001:未解析的外部符号“ public:虚拟结构QMetaObject const * __cdecl`匿名命名空间':: CUtility :: metaObject(void)const“(?metaObject @ CUtility @?A0x27a8253c @@ UEBAPEBUQMetaObject @@ XZ)
LNK2001:未解析的外部符号“ public:虚拟void * __cdecl“匿名命名空间” :: CUtility :: qt_metacast(char const *)”(?qt_metacast @ CUtility @?A0x27a8253c @@ UEAAPEAXPEBD @ Z)
LNK2001:尚未解决的外部符号“ public:虚拟int __cdecl“匿名命名空间” :: CUtility :: qt_metacall(枚举QMetaObject :: Call,int,void * *)”(?qt_metacall @ CUtility @?A0x27a8253c @@ UEAAHW4Call @ QMetaObject @@ HPEAPEAX @ Z)罪恶解决者
这与匿名名称空间完全无关。实际上,它们是不合逻辑的。
回想一下,moc生成了一些方法的实现,包括信号和一些静态数据。为此,类声明对于moc输出必须是可见的。在.cpp
文件末尾可见。
因此,要Q_OBJECT
在foo.cpp
文件中包含类,您必须#include "foo.moc"
在该文件的末尾。然后重新运行qmake并再次构建项目。就这样。
在下面的完整示例中,Utility
该类可以位于匿名名称空间中,但不一定必须如此。匿名名称空间不是“真正”的名称空间:它具有特殊的含义,它将所包含的标识符的范围限制在翻译单元内。就像一样static
,除了它还可以应用于类型,不仅是函数和变量。
// main.cpp #includenamespace { class Utility : public QObject { Q_OBJECT public: Utility(QObject *parent = {}); }; } Utility::Utility(QObject *parent) : QObject(parent) {} int main() { Utility utility; } #include "main.moc"