【问题标题】:How to achieve enum names like Qt::LeftDockWidgetArea如何实现像 Qt::LeftDockWidgetArea 这样的枚举名称
【发布时间】:2012-04-26 07:25:17
【问题描述】:

在使用 Qt 时,许多函数都接受一个参数,例如标志 Qt::LeftDockWidgetArea。

即使我浏览了 Qt 源代码,我也无法理解如何实现 这种命名行为。它是通用的 C++ 还是特定于 Qt 的?

假设我有一个班级MyClass

class MyClass {
    public:
        MyClass();
        void setFlag(???);
};

我想这样调用 setFlag 方法:

MyClass mc;
mc.setFlag(MyClass::flag1 | MyClass::flag2)

flag1 和 flag2 应该只是 0x01 和 0x02,这是一个枚举吗? 我必须在哪里声明? 该方法的参数是什么?

如果这很明显,我很抱歉,但我不明白。

解决方案(来自答案)

非常好。通过阅读下面的答案,我添加了这个: (请注意,我并不真正需要标志,只需要来自枚举的数字,这大大简化了它)

namespace MyNames {
    typedef enum {
        FA = 0,
        FB = 1
    } Field;
}

class MyClass
{
    public:
        MyClass();
        char getField(MyNames::Field f) const;
};

这确实允许以下调用(不):

mc.getField(MyNames::FA) //OK
mc.getField(1)           //not OK

【问题讨论】:

  • 但是,您的解决方案没有 Qt 标志的标志行为。它解决了一个完全不同的问题。
  • 是的。我真的很抱歉。这是我写标志问题时的错误。我很乐意将解决方案扩展为包含枚举的二进制运算符。 (它们的值可以很容易地更改为 0x01、0x02、0x04...)
  • 但是如果您想允许 MyNames::Field 枚举值的 OR 组合,您的输入参数类型不能再简单地是 MyNames::Field,即使您可以轻松地重新定义它们的值。例如。 mc.getField(MyNames::FA | MyNames::FB);如果您只重新定义 FA = 0x01 和 FB = 0x02,将会失败。
  • 如果你知道怎么做,如果你能在答案中解释它,我会很高兴 - 我们可以改进解决方案。

标签: c++ qt enums


【解决方案1】:

看看Qt::LeftDockWidgetArea的定义:

enum DockWidgetArea {
    LeftDockWidgetArea = 0x1,
    RightDockWidgetArea = 0x2,
    TopDockWidgetArea = 0x4,
    BottomDockWidgetArea = 0x8,

    DockWidgetArea_Mask = 0xf,
    AllDockWidgetAreas = DockWidgetArea_Mask,
    NoDockWidgetArea = 0
};

Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)

注意Q_DECLARE_FLAGS 宏,它通过创建QFlags typedef 来实现您所询问的行为。见http://qt-project.org/doc/qt-4.8/qflags.html#Q_DECLARE_FLAGS

【讨论】:

  • 请注意,C++ 是强类型的,不会自动为枚举重载operator|LeftDockWidgetArea | RightDockWidgetArea 需要 DockWidgetArea operator|(DockWidgetArea, DockWidgetArea)
  • MSalters: enum Foo { Hello };枚举栏 { 世界 }; ... int x = 你好|世界;工作得很好。
  • 以防万一有人想知道:MSalters 所说的运算符,可以通过 Q_DECLARE_OPERATORS_FOR_FLAGS(MyFlags) 轻松声明
【解决方案2】:

如果您仔细查看 Qt 文档(http://doc.qt.io/archives/qt-4.7/qt.html#DockWidgetArea-enum 针对您的特定情况),您会发现 Qt 使用模板化的 QFlags 类以类型安全的方式存储枚举值的 OR 组合。

编辑:看起来有两种答案,因为您的问题不是很清楚。仔细阅读您的问题后,我认为以下是您想要的。

class MyClass {
    public:
        enum Flags{
            Flag1 = 0x01,
            Flag2 = 0x02
        }
        MyClass();
        void setFlag(int Flags);//Not type-safe but works.
        void setFlag(Flags<MyClass::Flags> Flags);//Type-safe but you have to create a Flags class yourself
};

更多解释可以在这里的一个老问题中找到: How to use enums as flags in C++?

【讨论】:

  • 无需手动创建自定义类。请参阅 hc_ 的答案中的 Q_DECLARE_FLAGS。
  • 是的,你是对的,前提是他实际上在他的项目中使用 Qt 库,而不仅仅是试图用他自己的代码来模拟 Qt 库代码。
  • 我确实想用纯 C++ 模拟它。我编辑了我的问题以包含您的枚举,现在如何使方法类型安全?
  • HWende:对不起。我不是模板方面的专家,因此我无法对此给出可靠的答案。我只是建议您通过参考 Qt 库的源代码来尝试执行与 Qt 库中相同的操作。
【解决方案3】:

你会在src\corelib\global\qnamespace.h找到这个(或类似的东西):

#ifndef Q_MOC_RUN
namespace
#else
class Q_CORE_EXPORT
#endif
Qt {

这通常变得简单

namespace Qt {

要引用在此 Qt 命名空间中声明的名称(例如 LeftDockWidgetArea),请在其前面加上 Qt::

【讨论】:

  • 好的。所以我添加了命名空间。我必须在命名空间中声明什么才能获得 Qt::something?
  • 任何东西。在这种情况下,enum DockWidgetArea { LeftDockWidgetArea,...} ;
猜你喜欢
  • 2012-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多