5

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

artoon
  • 729
  • 2
  • 14
  • 41
  • 1
    Just a thought, but would you need to declare the metatype for Bar, as well as Foo, since Bar is also a custom type for QVariant? As the docs state "Note: If you are working with custom types, you should use the Q_DECLARE_METATYPE() macro to register your custom type." – TheDarkKnight Jan 09 '15 at 09:19
  • Sorry, Bar is also declared as metatype. – artoon Jan 09 '15 at 09:21
  • did you register types? – BЈовић Jan 09 '15 at 09:36
  • Yes I tried : qRegisterMetaType("Foo*"); qRegisterMetaType("Foo"); qRegisterMetaType("Bar*"); qRegisterMetaType("Bar"); but I have the same problem. – artoon Jan 09 '15 at 09:44

2 Answers2

7

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.

Wintermute
  • 42,983
  • 5
  • 77
  • 80
0

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.

Marek R
  • 32,568
  • 6
  • 55
  • 140