QT_BEGIN_NAMESPACE 和 QT_END_NAMESPACE

Qt 4 是没有命名空间的,从 Qt 5 开始,Qt 源码增加了可以将所有组件编译到命名空间 QT_NAMESPACE 的编译选项,尽管如此,官方发布的二进制版本默认是没有命名空间的。出于某种需要,可能有人选择将 Qt 编译成带命名空间 QT_NAMESPACE 的版本。为了让用户代码可以在有命名空间和没有命名空间的 Qt 下都能编译通过,可以在用户代码中添加宏 QT_BEGIN_NAMESPACE 和 QT_END_NAMESPACE。查看 Qt 源码就可以明白这对宏的含义:

  • qglobal.h 节选
#if !defined(QT_NAMESPACE) || defined(Q_MOC_RUN)
# define QT_BEGIN_NAMESPACE
# define QT_END_NAMESPACE
#else
# define QT_BEGIN_NAMESPACE namespace QT_NAMESPACE {
# define QT_END_NAMESPACE }

编译 Qt 源码时,编译选项 QT_NAMESPACE 将决定编译出来的 Qt 是否带命名空间 QT_NAMESPACE。

要查看自己的 Qt 是否是带命名空间的,可以用类似源码的条件判断:

#if !defined(QT_NAMESPACE) || defined(Q_MOC_RUN)
    qDebug() << "no QT_NAMESPACE";
#else
    qDebug() << "QT_NAMESPACE exists";
#endif

代码 QT_BEGIN_NAMESPACE class QLabel; QT_END_NAMESPACE, 带命名空间的 Qt 中被预处理为 namespace QT_NAMESPACE { class QLabel; },而在不带命名空间的 Qt 中被处理为 class QLabel;,而在绝大多数的情况下,我们获得的 Qt 预编译版本都是默认不带命名空间的,所以宏QT_BEGIN_NAMESPACE 和 QT_END_NAMESPACE 往往可以将它们无视掉。为了持有带命名空间的 Qt 的少数人,增加了 QT_BEGIN_NAMESPACE 和 QT_END_NAMESPACE 这对宏,难免让一般用户疑惑。但是 Qt 为了让用户代码实现跨平台构建,在有命名空间差异的 Qt 版本上都能构建成功,其作出的努力是值得肯定的。