Полиморфизм с QVariant

У меня есть два класса, как это:

class Foo
{
public:
Foo(int i) : _i(i) {}
int _i;
};
Q_DECLARE_METATYPE(Foo*)
class Bar : public Foo
{
public:
Bar(int i, int j) : Foo(i), _j(j) {}
int _j;
};
Q_DECLARE_METATYPE(Bar*)

Моя скамейка такая:

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Bar* bar = new Bar(10,11);
QVariant var = QVariant::fromValue(bar);
Foo * foo = var.value<Foo*>();            // foo IS NULL
QPushButton * b = new QPushButton();
QVariant v = QVariant::fromValue(b);
QObject * object = v.value<QObject*>();       // object  IS NOT NULL
return a.exec();
}

Почему foo ноль ?
QVariant позволяет полиморфизм, так как у меня нет проблем с object

4

Решение

Так как Foo не является производным от QObject а также QVariant поддерживает только полиморфизм для QObjectТипы

От QVariant :: value документация:

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

(Акцент мой). Это перефразировано в части о QVariant::canConvert на него ссылаются ниже, и нет ничего более о преобразовании указателя. QVariant просто не поддерживает ваш сценарий.

Плюс в том, что если вы сделаете Foo подкласс QObjectВы не должны беспокоиться о Q_DECLARE_METATYPE больше.

6

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

Проблема в том, что нет метаданных о наследовании и нет виртуальной таблицы, поэтому QVariant не имеет данных о наследовании. Вы можете попробовать добавить какой-нибудь виртуальный метод в базовый класс (лучше всего использовать деструктор), это может помочь (в этом случае будут некоторые данные о наследовании во время выполнения), но я не думаю, что этого достаточно.
Как и в других ответах, эта функция наверняка будет работать QObjects.

Вы также можете попробовать добавить Q_GADGET макрос для предоставления метаданных, но я сомневаюсь, что это решит проблему.

0

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