Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism with QVariant

I have two classes like this :

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*)

My bench is like this :

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();
}

Why is foo null ? QVariant lets the polymorphism since I have no problem with object

like image 533
artoon Avatar asked Jan 09 '15 09:01

artoon


1 Answers

Because Foo is not derived from QObject and QVariant only supports polymorphism for QObject-derived types.

From the QVariant::value documentation:

If the QVariant contains a pointer to a type derived from QObject then T may be any QObject type. If the pointer stored in the QVariant can be qobject_cast to T, then that result is returned. Otherwise a null pointer is returned. Note that this only works for QObject subclasses which use the Q_OBJECT macro.

(Emphasis mine). This is rehashed in the part about QVariant::canConvert that is referenced further down, and there is nothing else about pointer conversions. QVariant simply does not support your scenario.

The upside is that if you make Foo a subclass of QObject, you do not have to bother with Q_DECLARE_METATYPE anymore.

like image 82
Wintermute Avatar answered Sep 23 '22 01:09

Wintermute