考虑以下类定义:
// exported.hpp
#include <QObject>
class Exported: public QObject {
Q_OBJECT
public:
using QObject::QObject;
enum class FOO { BAR };
Q_ENUM(FOO)
};
以下main
文件:
// main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include "exported.hpp"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<Exported>("Package", 1, 0, "Exported");
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
通过这样做,我可以在QML中轻松访问枚举的命名常量 举个例子:
// main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import Package 1.0
ApplicationWindow {
Rectangle {
Component.onCompleted: {
console.log(Exported.BAR)
}
}
}
只要枚举的声明包含在类中,这就可以工作 例如,如果我更改了如下所示的类定义,它就不再起作用了:
// exported.hpp
#include <QObject>
enum class FOO { BAR };
class Exported: public QObject {
Q_OBJECT
public:
using QObject::QObject;
using FOO = ::FOO;
Q_ENUM(FOO)
};
现在,QML文件中的Exported.BAR
为undefined
。
最基本的问题是:为什么它不能使用使用声明?
请注意,它适用于转发声明,例如:
// exported.hpp
#include <QObject>
enum class FOO { BAR };
class Exported: public QObject {
Q_OBJECT
public:
using QObject::QObject;
enum class FOO;
Q_ENUM(FOO)
enum class FOO { BAR };
};
实际上Q_ENUM
实际上是documentation(强调我的):
此宏使用元对象系统注册枚举类型。 必须放在具有Q_OBJECT或Q_GADGET宏的类中的枚举声明之后。
整个部分没有提及定义。
另一方面,我们从标准中得到了这个:
using声明将一组声明引入声明区域,其中出现using声明。
所以,我期待它也可以运作。无论如何,这可能是我个人的错误期望。
那说,有关如何处理这么不方便的任何建议吗?
如果在类中定义 enum ,我可以看到解决它的唯一方法是在类中定义另一个 enum 并且具有一对一的一对一它们之间的映射。
它确实远没有可维护性和有点乏味。
答案 0 :(得分:1)
这与标准C ++无关,至少不是直接的。 Qt的moc在理解C ++语法规则方面非常有限(并且有充分的理由 1 )。显然,这种将枚举导入类范围的方式超出了它的能力范围。
在我的代码中,当我想要moc生成枚举&lt; - &gt;字符串转换对我来说,我使用别名,但方向相反:
class Exported: public QObject {
Q_OBJECT
public:
using QObject::QObject;
enum class FOO { BAR };
Q_ENUM(FOO)
};
using FOO = Exported::Foo;
这使得moc很开心并且是有效的C ++。不利的一面是,您将Exported
的定义提取到您使用FOO
定义的每个范围内,并且您无法转发声明FOO
。
1 它是在libclang之前创建的,并且针对一些极端情况的完整C ++解析器的实现成本非常不经济。