如果 Q_OBJECT 宏被其他宏删除,则无法编译 MOC 文件:头文件不包含 <QObject>

Posted

技术标签:

【中文标题】如果 Q_OBJECT 宏被其他宏删除,则无法编译 MOC 文件:头文件不包含 <QObject>【英文标题】:Cannot compile MOC file if Q_OBJECT macro is removed by other macro: The header file doesn't include <QObject> 【发布时间】:2012-04-29 17:53:19 【问题描述】:

在编译非 Qt 版本的 Qt/C++ 程序 (-DDISABLE_MYMODULE) 时,我收到以下编译器错误:

src/mymodule.moc.cpp:12:2: error: #error "The header file
'mymodule.hpp' doesn't include <QObject>."
src/mymodule.moc.cpp:19:1: error: ‘QT_BEGIN_MOC_NAMESPACE’ does not name a type
src/mymodule.moc.cpp:40:6: error: ‘MyModule’ has not been declared
...

我正在使用 GNU make(不是 qmake)。我的 Makefile 为每个模块编译两个目标文件,一个直接来自 .cpp 源文件,另一个来自 .moc.cpp 源文件(这是行不通的),两者都使用 g++。此 .moc.cpp 源文件由 MOC 从 .hpp 标头创建(此过程不会引发错误)。

有问题的头文件看起来有点像这样:

#ifndef DISABLE_MYMODULE //My problem macro
#ifndef MYMODULE_HPP
#define MYMODULE_HPP
//...
class MyModule : //...

    Q_OBJECT //Qt problem macro
    //...
;
//...
#endif
#endif

如果不设置我的问题宏,整个事情都会编译(然后链接,执行)就好了。如果我确实设置了它,但注释掉 QT 的问题宏,它也会编译得很好(构建一个非 Qt 版本)。

我不完全知道,MOC 用什么替换 Q_OBJECT,但它不应该仍然在我的 DISABLE_MYMODULE 中并因此被预处理器删除吗?

【问题讨论】:

【参考方案1】:

看起来您的宏 DISABLE_MYMODULE 排除了类定义,其中包括 Q_OBJECT。另一方面,此代码仍由 moc 工具处理,该工具会生成您的 mymodule.moc.cpp 文件,该文件又包含您的 mymodule.hpp 头文件。当 mymodule.moc.cpp 然后由编译器处理时,它包含 .hpp 文件,但由于 DISABLE_MYMODULE,预处理器排除了它的内容,所以编译器找不到类的定义,#include 和应该扩展 Q_OBJECT 宏的东西.所以编译器没有找到它期望的东西并变得不安......

我认为,如果定义了 DISABLE_MYMODULE,解决方案是从构建中排除 mymodule.moc.cpp,或者如果定义了 DISABLE_MYMODULE,则(更好)禁用 mymodule.hpp 上的 moc 处理。

【讨论】:

【参考方案2】:

尝试检查下一个条件:

    类应直接或间接继承自 QObject,且 QObject 必须在继承列表中排在首位。 类在单独的 *.h 和 *.cpp 文件中定义和实现。如果没有,则需要在实现和定义类的文件末尾添加#include "you_cpp_file.moc"。

【讨论】:

以上是关于如果 Q_OBJECT 宏被其他宏删除,则无法编译 MOC 文件:头文件不包含 <QObject>的主要内容,如果未能解决你的问题,请参考以下文章

为啥打开word是提示说由于宏安全设置,无法找到宏或宏被禁用

如果在具有 Q_OBJECT 宏的类之外,则无法在 Qt Linguist 中获取字符串

由于宏安全设置,无法找到宏或宏被禁用怎么办?

如果我只使用插槽,是不是需要使用 Q_OBJECT 宏?

如何在 Xcode 中使用 Q_OBJECT 宏编译头文件?

使用 static_assert 检查 Q_OBJECT 宏