如何以及何时使用 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)如果我删除它,它告诉我我没有声明它。 这看起来你的 .h 文件确实缺少包含保护(#pragma once 或 #ifndef FILENAME #define FILENAME)

以上是关于如何以及何时使用 Q_DECLARE_METATYPE的主要内容,如果未能解决你的问题,请参考以下文章

何时以及如何使用 Tornado?啥时候没用?

如何以及何时使用 Ember.Application 注册和注入方法?

我如何知道何时索引列以及使用啥索引?

何时以及如何使用 PySide QEventLoop

JSF 中的“绑定”属性如何工作?何时以及如何使用它?

JSF 中的“绑定”属性如何工作?何时以及如何使用它?