Q_OBJECT宏做什么?为什么所有Qt对象都需要此宏?


131

我刚刚开始使用Qt,并注意到所有示例类定义都以宏Q_OBJECT作为第一行。此预处理程序宏的目的是什么?


25
QT指的是QuickTime,Qt指的是称为Qt的C ++库。
Bleadof

Answers:


132

Qt文档中

元对象编译器moc是处理Qt的C ++扩展的程序。

moc工具读取C ++头文件。如果找到包含Q_OBJECT宏的一个或多个类声明,它将生成一个C ++源文件,其中包含这些类的元对象代码。除其他事项外,信号和时隙机制,运行时类型信息和动态属性系统还需要元对象代码。


为什么我不需要显式写Q_OBJECT::connect()而只需要写connect()
mLstudent33,

19

它只是告诉预编译器该类具有gui元素,并且需要通过“ moc”运行,您只需要将其添加到使用signal / slot机制的类中即可。
但是在任何其他类中它将被静默忽略-它只会增加构建时间。


3
同样是错误的,您仅在使用信号/插槽机制的类上需要它。缺少Q_OBJECT中断qobject_cast和内省。它可能导致一些令人困惑的行为,所以这是一个坏主意。
恢复莫妮卡

2
Q_OBJECT在任何其他(非QObject)类中都将被“安静地”忽略是不正确的。根据C ++标准,它通过声明一些从未定义的成员函数和变量来引入未定义的行为。它还会使用QObject-specific成员污染类的名称空间。例如,很Q_OBJECT可能会破坏一个不相关的类,该类恰好包含一个称为的方法metaObject
恢复莫妮卡

2
错了 尽管您可能想为大多数gui类配备Q_OBJECT宏,但是让非gui类具有宏以及没有宏的gui类完全有意义。该宏很有用,但不仅限于gui类,也不是必需的。
pasbi

9

MOC(元对象编译器)将包含Q_OBJECT宏的头文件转换为等效的C ++源代码。它基本上控制信号时隙机制,并使C ++编译器可以理解


2
这是错误的:Q_OBJECT宏由编译器扩展,因此不需要moc。moc不会对宏本身做任何事情,但是会生成宏声明的成员变量和方法的定义Q_OBJECT
恢复莫妮卡

5

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命令中。


2

在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 {};

0

Q_OBJECT宏必须出现在一个类定义的私有部分中,该类声明其自身的信号和插槽,或者使用Qt的元对象系统提供的其他服务。


1
这具有误导性:Q_OBJECT宏必须出现在从派生的每个类中QObject。当宏不存在时,您的代码将被巧妙地破坏,并且仅仅因为它恰好可以编译而无法正常运行。
恢复莫妮卡

@KubaOber您是否有一个示例代码可以编译,但是在Q_OBJECT缺少宏时不起作用?
克里斯(Chris)

2
如果查看的实现Q_OBJECT,您会发现它使用访问说明符。因此,无论宏应该出现在之下privateprotectedpublic说明符是无关紧要的-它只是将其放置在类的头约定。
TrebledJ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.