2

我想使用 Qt 的反射机制,因为 C++ 缺少这个特性。它似乎工作,但调用所有的宏和辅助函数是非常乏味的。例如,要将枚举注册为适当的元类型,我必须完成以下所有步骤:

  1. 在包含Q_GADGET宏的包装类中声明一个枚举。
  2. Q_ENUM之后使用宏注册枚举。
  3. 注册包含枚举的类:Q_DECLARE_METATYPE(MyClass)
  4. 调用qRegisterMetaType<..>()包装类的类型和每个声明的枚举。

现在我知道,如果不需要完整功能的一部分,可以省略一些步骤。但这不是我想要的,我需要在信号中使用枚举,并且我需要能够获取信号的元方法并查询它的参数类型。

但我仍然不禁想到必须有更好/更简单的方法来做到这一点。

4

1 回答 1

6

不幸的是,你不能做的比这少。

  • Q_GADGET(或者Q_OBJECT,对于 QObject 子类)意味着“为这个类生成元对象信息”。
  • Q_ENUM意思是“为这个特定的枚举生成元枚举信息”。现在有人可能会争辩说,注册类中的所有(公共?)枚举也应该自动注册。但由于这有成本(二进制大小),而且我们使用 C++,我们不想为我们永远不会在元对象系统中使用的枚举付费,所以它是可选的。
  • Q_DECLARE_METATYPE(如果您正在使用枚举本身,则Q_ENUM不需要;在您的场景中通常不需要)使该类型能够在QVariants 内使用(Qt 的 C++98,C++17 的无 RTTI 化身std::any)。你是否想要这个取决于类型。我会说所有“值类型”都应该有它,但同样,这会产生你可能不想支付的额外代码。此外,这实际上仅适用于“值类型”——此注册要求类型具有公共默认构造函数、公共复制构造函数、公共复制赋值、公共析构函数。如果你有一个没有这些的类,你不能使用这个宏 => 你不能把它包装在一个QVariant.
  • qRegisterMetaType在运行时在表中注册上述构造函数/析构函数,使您能够拥有类型的唯一 ID(如果您想在方法签名中识别类型,则需要),动态创建或销毁该类型的实例(除其他外,需要,实现排队连接:Qt 需要一种通用的方法来将信号的参数复制到要发送到目标线程的事件中,并在稍后销毁这些参数),使用 Q_PROPERTY 子系统。

根据您需要做什么,您需要所有这些的一个子集。

于 2016-11-08T11:11:59.767 回答