在匿名命名空间中定义QObject派生类
Define a QObject derived class inside an anonymous namespace?
我正在使用Qt 5.7(C++)。
在一个类的cpp文件中,我使用一个匿名命名空间来创建一个类(一些实用程序),我将只在该文件中使用该类。
但是,如果实用程序类是从Qt类派生的,则会出现Linking错误。我认为问题出在Q_OBJECT宏上,如果我不添加它,我就不会得到错误。但在任何Qt派生类中,都必须/建议使用Q_OBJECT宏。
我该如何避免这种情况?是否有其他方法可以创建具有文件作用域的实用程序类
显示错误的简单示例:类CMyClass使用从QWidget派生的实用程序类(名为CUtility)。
谢谢。
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();
}
错误为:
LNK2001:未解析的外部符号"public:virtual struct QMetaObject const*__cdecl`匿名命名空间'::CUtility::metaObject(void)const"(?metaObject@CUtility@?A0x27a8253c@@UEBAPEBUQMetaObject@@XZ)
LNK2001:未解析的外部符号"public:virtual void*__cdecl`匿名命名空间'::实用性:qt_metacast(char const*)"(?qt_metacast@CUtility@?A0x27a8253c@@UEAAPEAXPEBD@Z)sin分解器
LNK2001:未解析的外部符号"public:virtual int __cdecl`anonynamespace'::CUtility::qt_metacall(enum QMetaObject::Call,int,void**)"(?qt_metacall@CUtility@?A0x27a8253c@@UEAAHW4Call@QMetaObject@@HPEAPEAX@Z)sin分解器
这与匿名命名空间完全无关。事实上,它们是不合逻辑的。
回想一下,moc生成了一些方法的实现,包括信号和一些静态数据。为了实现这一点,类声明必须对moc输出可见。它在.cpp
文件的末尾可见。
因此,要在foo.cpp
文件中有一个Q_OBJECT
类,必须在该文件的末尾有#include "foo.moc"
。如果使用cmake,则只需重新构建,或者,对于qmake,首先重新运行qmake然后构建项目。仅此而已。
在下面的完整示例中,Utility
类可以在匿名命名空间中,但不一定要在;真的";名称空间:它有一个特殊的含义,将包含的标识符的范围限制为翻译单元。它类似于static
,只是它也可以应用于类型,而不仅仅是函数和变量。
// main.cpp
#include <QObject>
namespace {
class Utility : public QObject {
Q_OBJECT
public:
Utility(QObject *parent = {});
};
}
Utility::Utility(QObject *parent) : QObject(parent) {}
int main() {
Utility utility;
}
#include "main.moc"
它不适用于Q_OBJECT
宏,因为宏会向类添加成员,这些成员在moc生成的C++代码中定义(通常在moc_CMyClass.cpp
中,使其与文件范围不兼容)。
一种可能的解决方案是跳过Q_OBJECT
宏,它不是强制性的,你可能不需要它。缺点是你会丢失关于你的类的内省信息,并且不能声明信号和槽。
另一种解决方案是,正如@KubaOber所建议的,在您自己的副本文件的末尾包含生成的cpp文件。在这种情况下,qmake
将检测到它,并且不会编译moccpp文件本身。
- 为什么使用 "this" 指针调用派生成员函数?
- winapi - 从 QObject 派生类调用时 GetMessage() 崩溃
- 在匿名命名空间中定义QObject派生类
- 如果从 QObject 派生的类的构造函数抛出,则将发出 destroy()
- 为什么QList不是从QObject派生出来的?
- 在Linux上的命令行上编译QObject派生类
- 我应该何时从QObject派生类
- 转储QObject派生对象的所有属性
- 在 QObject 派生类中重复Q_DISABLE_COPY
- 如何重写 QObject::findChildren 以仅返回派生类型
- 定义自己的析构函数,尽管类派生自QObject
- QObject派生的类回调函数到c库
- 使用宏创建QObject派生类
- 如果QObject是从direct派生的,那么使用“虚拟”多重继承是否安全?
- 如何正确使用qRegisterMetaType类派生自QObject
- 在派生的QObject构造函数中连接Qt信号和槽
- 缺少QObject派生类
- 是否有一种方法可以获得QObject派生类的类名而不创建该类的实例化?
- 类与虚函数,当从QObject派生时,导致链接错误
- QList子-从QObject派生的结构或自定义类