Как и когда использовать Q_DECLARE_METATYPE

Мне нужно привести 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, что я пропускаю?

5

Решение

Вы должны поместить Q_DECLARE_METATYPE (QSqlRecord) только в один заголовок, а затем просто включить его там, где это необходимо. Q_DECLARE_METATYPE (QSqlRecord) должен находиться вне любых классов и пространств имен.
Из документации Qt:

В идеале этот макрос должен быть помещен ниже объявления класса или структуры. Если это невозможно, его можно поместить в закрытый заголовочный файл, который должен включаться каждый раз, когда этот тип используется в QVariant.

5

Другие решения

Ты используешь 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

2

По вопросам рекламы [email protected]