Polymorphism with QVariant

1.5k views Asked by At

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

2

There are 2 answers

0
Wintermute On BEST ANSWER

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.

0
Marek R On

Problem is that there is no meta data about inheritance and no virtual table, so QVariant has no data about inheritance. You can try add some virtual method to base class (destructor would be best), it might help (in such case there will be some run time data about inheritance) but I don't think it is enough.
Like in other answer this feature will work for sure for QObjects.

You can also try add Q_GADGET macro to provide meta data, but I doubt it will solve the problem.