【问题标题】:Why is it not possible to use Q_OBJECT with template classes?为什么不能将 Q_OBJECT 与模板类一起使用?
【发布时间】:2020-07-21 18:25:45
【问题描述】:

有一个类似的问题 here 正在寻找一种解决方法和一个很好的指南 here 它描述了 Qt 中的元对象系统。但这并不能直接解释为什么不能使用模板类在元对象系统中。这是一个烦人的限制。

有人知道为什么吗?

【问题讨论】:

  • 好吧可能是由宏生成的东西引起的,如果每个类都必须有一些唯一的 Q_OBJECT id(示例),则模板的不同实例化将产生具有相同 ID 的不同类,因为宏是在编译之前执行的,但这只是一个想法,因为我知道 Q_OBJECT 宏产生了什么
  • 这听起来像是 xy 问题。你想达到这个特定限制禁止的目的是什么?
  • @G.M.我想编写一个辅助类来在大量.ui 文件中运行所需形式的->setupUi。问题是这些形式的顶级类不同(例如QDialog 或QMainWindow)所以我决定使用模板如果那个助手类不使用信号和槽机制(这里就是这种情况),那么没问题。但我想知道为什么会有这样的限制?跨度>
  • @Berto99 好主意。事实上,data structure 关于元对象系统中的类比 id 更复杂,但如果类签名应该具有相同 QMetaObject 实例的实例不同。所以 moc 将阻止您在包含 Q_OBJECT 的类中使用模板。
  • 您可以在基类中有一个 void*(或基类型)信号,并让模板类(对应于实际类型)连接到重新解释返回的模板槽(很像 moc 开始时所做的事情和)。您也可以只使用自动生成的 moc 代码并将模板添加到类定义中,尽管我只会在私人项目中这样做。

标签: c++ qt templates qt5 qmetaobject


【解决方案1】:

在标准 Qt 中是不可能的*,对于 Qt,对于这些类,moc 需要能够预处理类并生成所需的元数据结构。这是在编译之前完成的,对于模板类,这意味着类型还没有真正定义。

但是,有些事情是可能的:

  • QObject 可以有模板化方法,只要它们没有被标记为可调用、槽或信号。
  • 您可以创建一个继承 QObject 派生类的模板类。它不能有 Q_OBJECT 宏或添加信号、槽或属性,但它可能是一个有用的技巧,例如创建模板化的通用 QAbstractItemModel。
  • 您可以使用 Verdegris 代替 moc。它使用基于模板的替代 moc 来生成 moc 兼容的代码。这也应该允许模板化的 QObjects。

*) 当然没有什么是不可能的...如果其他一切都失败了,您也可以实现 moc 提供的所有内容...

【讨论】:

  • 不错!我还没有听说过 Verdigris。而且看起来 MOC 和 Verdigris 之间在宏方面有很多 similarities。所以这是 MOC 本身的一个缺陷无法处理模板。实际上在实际实践中几乎没有需要同时使用模板和信号槽机制的情况。但是您的回答揭示了原因。谢谢:)
  • 我不会称之为缺陷。 moc 之所以如此,是有历史原因的。 Verdegris 使用了最近才成为可能的 c++,而带有 moc 的 Qt 已经被证明有用了大约 25 年。在 Qt 支持的编译器甚至支持模板化之前。
  • @André 也许这是 25 年前最好的解决方案,但他们当然不必继续将其延续到 Qt5 和 Qt6(至少需要 C++17)。跨度>
猜你喜欢
  • 2021-08-13
  • 2014-06-18
  • 2017-03-13
  • 1970-01-01
  • 2017-03-16
  • 2011-06-05
  • 2021-10-23
  • 2020-08-26
  • 2013-07-02
相关资源
最近更新 更多