我刚开始使用 Qt,注意到所有的示例类定义都以宏 Q_OBJECT作为第一行。这个预处理器宏的用途是什么?
Q_OBJECT
来自 Qt 文档:
元对象编译器 moc 是 处理 Qt 的 C + + 的程序 接发。 Moc 工具读取一个 C + + 头文件。 如果它找到一个或多个类 包含 Q _ OBJECT 的声明 宏,它生成一个 C + + 源文件 包含元对象代码的 那些课程。除了其他事情, 元对象代码是必需的 信号和插槽机构, 执行期型态讯息 动态产权制度动态产权制度。
元对象编译器 moc 是 处理 Qt 的 C + + 的程序 接发。
Moc 工具读取一个 C + + 头文件。 如果它找到一个或多个类 包含 Q _ OBJECT 的声明 宏,它生成一个 C + + 源文件 包含元对象代码的 那些课程。除了其他事情, 元对象代码是必需的 信号和插槽机构, 执行期型态讯息 动态产权制度动态产权制度。
它只是告诉预编译器,这个类需要通过‘ moc’(元对象编译器)运行,它向类添加额外的隐藏字段和函数,以及解析信号和插槽。您只需要将它添加到使用信号/槽机制或其他 Qt 类级别特性(如内省)的类中。您不需要将 Q _ OBJECT 添加到只使用标准 C + + 特性的类中。
MOC (元对象编译器)将 Q _ OBJECT 宏包含的头文件转换为 C + + 等效的源代码。 它基本上控制了信号槽机制,使 C + + 编译器能够理解它
Q _ OBJECT 宏必须出现在类定义的私有部分中,该类定义声明自己的信号和插槽,或者使用 Qt 的元对象系统提供的其他服务。
1来自 元对象系统的 Qt 文档
Moc 工具读取一个 C + + 源文件。如果它发现一个或多个包含 Q _ OBJECT 宏的类声明,它将生成另一个 C + + 源文件,其中包含每个类的元对象代码。这个生成的源文件或者 # include’d 到类的源文件中,或者更常见的是,编译并链接到类的实现中。
2来自 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~的 Qt 文档
3来自 一个 href = “ https://doc.qt.io/qt-5/moc.html”rel = “ norefrer”> moc 的 Qt 文档
Moc 工具读取一个 C + + 头文件。如果它发现一个或多个包含 Q _ OBJECT 宏的类声明,它将生成一个包含这些类的元对象代码的 C + + 源文件。除此之外,信号和插槽机制、执行期型态讯息和动态属性系统都需要元对象代码。
4来自 信号和插槽 的 Qt 文档
预处理器扩展了 Q _ OBJECT 宏,声明了由 moc 实现的几个成员函数; 如果你得到了编译器错误,比如“对 LcdNumber 的 vtable 的未定义引用”,你可能已经忘记运行 moc 或者在 link 命令中包含 moc 输出。
在使用 -E的 gcc 中,可以看到扩展的宏。这就是 Q_OBJECT在 Linux 的 gcc 上展开的内容。请注意,这可能依赖于平台,并且可能根据 QT 的版本而改变。您可以看到它不仅仅是 moc 编译器的标记。
-E
# 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 {};