如何以及何时使用 Q_DECLARE_METATYPE
Posted
技术标签:
【中文标题】如何以及何时使用 Q_DECLARE_METATYPE【英文标题】:How and when to use Q_DECLARE_METATYPE 【发布时间】:2017-03-16 09:09:01 【问题描述】:我需要将 QSqlRecord 转换为 QVariant 并在整个项目中返回。为此,我添加了
Q_DECLARE_METATYPE(QSqlRecord);
在需要转换的类的 .h 文件中。 我还有一个基类,几个子类从该基类继承,在这种情况下,我假设在基类中只包含一次 Q_DECLARE_METATYPE 就足够了。因此,我有例如:
widgetBaseClass:声明元类型 widgetChildClass1:继承widgetBaseClass 不声明元类型 widgetChildClass2:继承 widgetBaseClass 不声明元类型 myTableModel:声明元类型当我尝试像这样运行程序时,我得到了
Redefinition of 'QMetaTypeId<QSqlRecord>
来自widgetBaseClass,指向myTableModel中的前一个声明。另一方面,如果我删除我得到的声明:
static_assert failed "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system");
根据我对 Q_DECLARE_METATYPE 工作原理的理解,这意味着如果我声明它,它会导致错误,因为它已经在其他地方声明,但如果我不声明它,我不能从 QVariant 转换,因为它没有将对象识别为有效的 QVariant,我缺少什么?
【问题讨论】:
【参考方案1】:您应该只将 Q_DECLARE_METATYPE(QSqlRecord) 放在一个标头中,然后将其包含在需要的任何地方。 Q_DECLARE_METATYPE(QSqlRecord) 必须在任何类和命名空间之外。 From Qt documentation:
理想情况下,这个宏应该放在类或结构的声明之下。如果这是不可能的,它可以放在一个私有头文件中,每次在 QVariant 中使用该类型时都必须包含该头文件
【讨论】:
感谢您的回复,我确实将 Q_DECLARE_METATYPE 放在了命名空间之外,但是它位于另一个类的 .h 文件中。我是否应该只创建一个包含我需要的所有 Q_DECLARE_METATYPE 的特定 .h 文件,并在需要时包含它? 来自 Qt 文档的@NicoloCastro >理想情况下,这个宏应该放在类或结构的声明之下。如果这是不可能的,它可以放在一个私有头文件中,每次在 QVariant 中使用该类型时都必须包含该头文件。 好的,谢谢,抱歉,我浏览了一下,显然没有注册该段落。【参考方案2】:您在具有公共构造函数、析构函数、复制构造函数的类上使用 Q_DECLARE_METATYPE
,因此 QSqlRecord 适合。只需确保每个类声明只使用此宏一次。可能你错过了一些#pragma once
?
在你自己的类上使用它,在类声明之后,在命名空间大括号之外:
//mystruct.h
namespace MyNamespace
struct MyStruct
int i;
...
;
Q_DECLARE_METATYPE(MyNamespace::MyStruct)
在此处查看文档:http://doc.qt.io/qt-5/qmetatype.html#Q_DECLARE_METATYPE
【讨论】:
为什么我不应该在 Qt 的类上使用声明元类型?如何将 QVariant 转换为 Qt 类?还是不应该允许我这样做? 抱歉,我从文档中刷新了我的信息并快速修复了答案。 哦,好的,谢谢。所以在我写的我知道我会强制转换的类中,我可以将声明直接放在同一个文件中,在命名空间之外,对于其他人我必须包含它,但这是我的问题,现在如果我包含它告诉我它已经包含(重新定义'QMetaTypeId以上是关于如何以及何时使用 Q_DECLARE_METATYPE的主要内容,如果未能解决你的问题,请参考以下文章