【问题标题】:Qt C++: Multiple Q_NAMESPACE for the same namespace in different filesQt C++:不同文件中相同命名空间的多个Q_NAMESPACE
【发布时间】:2020-02-01 00:53:45
【问题描述】:
  • 我有两个enums。它们在同一个命名空间中,但头文件不同。
  • 为了使它们可用于 Qt 元类型系统,我尝试这样做:
//C1.h
#include <QObject>
namespace SW
{
Q_NAMESPACE
enum class Enum1 {A, B};
Q_ENUM_NS(Enum1)
}
//C2.h
#include <QObject>
namespace SW
{
Q_NAMESPACE
enum class Enum2 {A, B};
Q_ENUM_NS(Enum2)
}
//main.c
#include <QDebug>
#include <QMetaEnum>

#include "C1.h"
#include "C2.h"

int main(int argc, char *argv[]) {
    auto me1 = QMetaEnum::fromType<SW::Enum1>();
    qDebug() << "me1 valid:" << me1.isValid();

    auto me2 = QMetaEnum::fromType<SW::Enum2>();
    qDebug() << "me2 valid:" << me2.isValid();
}
  • 上面我得到重复符号链接器错误。因为moc_C1.omoc_C2.o 都定义了staticMetaObject that result from Q_NAMESPACE
  • 我发现两个标题中的命名空间都必须包含Q_NAMESPACE。否则 moc 会报错“错误:命名空间声明缺少 Q_NAMESPACE 宏。”
  • 如果我只有 C1.h 或 C2.h 中的一个,它可以构建并正常工作。
  • 如果我将 C2.h 的内容移动到 C1.h,它也可以工作,并且会打印:
me1 valid: true
me2 valid: true
  • 如果我将 C2.h 的内容移动到 main.cpp(带或不带 Q_NAMESPACE),它会编译但在运行时出现故障:
me1 valid: true
me2 valid: false

问题:有没有办法将Q_NAMESPACE 用于分布在多个文件中的命名空间?

解决我能想到的这个问题的方法:

  • 将我的枚举包含在 Q_OBJECT 或 Q_GADGET 类中
  • 将我所有的枚举放在同一个文件中

【问题讨论】:

    标签: c++ qt


    【解决方案1】:

    根据他们的问题跟踪器QTBUG-68611,这似乎是一个已知错误

    在解决之前,我们将不得不忍受这个限制。

    或者,您可以(尽管我不建议)在文件结构之间有一个中间部分,例如:

    // internal/C1.h
    #include <QObject>
    enum class Enum1 {A, B};
    Q_ENUM_NS(Enum1)
    
    //internal/C2.h
    #include <QObject>
    enum class Enum2 {A, B};
    Q_ENUM_NS(Enum1)
    
    // C.h
    #include <QObject>
    namespace SW
    {
    Q_NAMESPACE
    #include internal/C1.h
    #include internal/C2.h
    }
    

    【讨论】:

      【解决方案2】:

      令我非常失望的是,这是不可能的。

      或者,Verdigris 库。它完全兼容 Qt 并启用 Qt 的功能,而无需调用 MOC,因此您不会收到缺少 Q_NAMESPACE 的错误。

      但您需要在 W_ENUM_NS 宏和某些源文件中的 W_NAMESPACE_IMPL 中列出所有枚举值

      //foo.h
      #pragma once
      
      #include "wobjectdefs.h"
      
      namespace lib
      {
      W_NAMESPACE(lib)
      
      enum class Foo {
          A,
          B,
      };
      W_ENUM_NS(Foo, Foo::A, Foo::B)
      
      } // namespace lib
      

      -

      // bar.h
      #pragma once
      #include "foo.h"
      #include "wobjectdefs.h"
      
      namespace lib
      {
      enum class Bar {
          A,
          B,
      };
      W_ENUM_NS(Bar, Bar::A, Bar::B)
      } // namespace lib
      

      -

      #include <QCoreApplication>
      #include <QDebug>
      
      #include "bar.h"
      #include "foo.h"
      
      #include "wobjectimpl.h"
      
      namespace lib
      {
      W_NAMESPACE_IMPL(lib)
      }
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          qDebug() << lib::Bar::A;
          qDebug() << lib::Foo::A;
          return a.exec();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-17
        • 1970-01-01
        • 1970-01-01
        • 2012-07-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多