我刚刚开始使用Qt,并注意到所有示例类定义都以宏Q_OBJECT
作为第一行。此预处理程序宏的目的是什么?
我刚刚开始使用Qt,并注意到所有示例类定义都以宏Q_OBJECT
作为第一行。此预处理程序宏的目的是什么?
Answers:
从Qt文档中:
元对象编译器moc是处理Qt的C ++扩展的程序。
moc工具读取C ++头文件。如果找到包含Q_OBJECT宏的一个或多个类声明,它将生成一个C ++源文件,其中包含这些类的元对象代码。除其他事项外,信号和时隙机制,运行时类型信息和动态属性系统还需要元对象代码。
Q_OBJECT::connect()
而只需要写connect()
?
它只是告诉预编译器该类具有gui元素,并且需要通过“ moc”运行,您只需要将其添加到使用signal / slot机制的类中即可。
但是在任何其他类中它将被静默忽略-它只会增加构建时间。
Q_OBJECT
中断qobject_cast
和内省。它可能导致一些令人困惑的行为,所以这是一个坏主意。
Q_OBJECT
在任何其他(非QObject
)类中都将被“安静地”忽略是不正确的。根据C ++标准,它通过声明一些从未定义的成员函数和变量来引入未定义的行为。它还会使用QObject
-specific成员污染类的名称空间。例如,很Q_OBJECT
可能会破坏一个不相关的类,该类恰好包含一个称为的方法metaObject
。
Q_OBJECT
宏,但是让非gui类具有宏以及没有宏的gui类完全有意义。该宏很有用,但不仅限于gui类,也不是必需的。
1来自Meta-Object System的 Qt文档
moc工具读取C ++源文件。如果找到包含Q_OBJECT宏的一个或多个类声明,它将生成另一个C ++源文件,其中包含每个这些类的元对象代码。生成的源文件或者包含在类的源文件中,或者更通常地,编译并与类的实现链接。
2来自Q_OBJECT的 Qt文档
Q_OBJECT宏必须出现在一个类定义的私有部分中,该类声明其自身的信号和插槽,或者使用Qt的元对象系统提供的其他服务。
3从Qt文档MOC
moc工具读取C ++头文件。如果找到包含Q_OBJECT宏的一个或多个类声明,它将生成一个C ++源文件,其中包含这些类的元对象代码。除其他事项外,信号和时隙机制,运行时类型信息和动态属性系统还需要元对象代码。
4来自Qt 信号和插槽的文档
Q_OBJECT宏由预处理器扩展,以声明由moc实现的几个成员函数。如果在“对LcdNumber的vtable的未定义引用”中遇到编译器错误,则可能已忘记运行moc或将moc输出包括在link命令中。
在gcc中,-E
您可以看到扩展的宏。这就是Q_OBJECT
在Linux上的gcc上扩展的内容。请注意,这可能取决于平台,并且可能会根据QT的版本进行更改。您可以看到它不仅是moc编译器的标签。
# 11 "mainwindow.hh"
#pragma GCC diagnostic push
# 11 "mainwindow.hh"
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wsuggest-override"
# 11 "mainwindow.hh"
static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); static inline QString tr(const char *s, cons
t char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } __attribute__ ((__deprecated__)) static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } private:
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wattributes"
# 11 "mainwindow.hh"
__attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
# 11 "mainwindow.hh"
#pragma GCC diagnostic pop
# 11 "mainwindow.hh"
struct QPrivateSignal {};
Q_OBJECT宏必须出现在一个类定义的私有部分中,该类声明其自身的信号和插槽,或者使用Qt的元对象系统提供的其他服务。
Q_OBJECT
宏必须出现在从派生的每个类中QObject
。当宏不存在时,您的代码将被巧妙地破坏,并且仅仅因为它恰好可以编译而无法正常运行。
Q_OBJECT
缺少宏时不起作用?
Q_OBJECT
,您会发现它使用访问说明符。因此,无论宏应该出现在之下private
,protected
或public
说明符是无关紧要的-它只是将其放置在类的头约定。