Полиморфизм с 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


person artoon    schedule 09.01.2015    source источник
comment
Просто мысль, но нужно ли вам объявлять метатип для Bar, а также для Foo, поскольку Bar также является пользовательским типом для QVariant? Как указано в документах. Примечание. Если вы работаете с пользовательскими типами, вам следует использовать макрос Q_DECLARE_METATYPE() для регистрации вашего пользовательского типа.   -  person TheDarkKnight    schedule 09.01.2015
comment
Извините, Bar также объявлен как метатип.   -  person artoon    schedule 09.01.2015
comment
ты прописал типы?   -  person BЈовић    schedule 09.01.2015
comment
Да, я пробовал: qRegisterMetaType‹Foo*›(Foo*); qRegisterMetaType‹Foo›(Foo); qRegisterMetaType‹Bar*›(Bar*); qRegisterMetaType‹Bar›(Bar); но у меня такая же проблема.   -  person artoon    schedule 09.01.2015


Ответы (2)


Поскольку 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.

person Wintermute    schedule 09.01.2015
comment
Спасибо за помощь. - person artoon; 09.01.2015

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

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

person Marek R    schedule 09.01.2015