0

I have the following simplified setup where I'm trying to access the Q_Properties on the inherited class of a class that inherits from QObject. I can access the properties of the base class just fine but I can't find or see (while debugging) the properties of my inherited class:

Base Class:

class Vehicle : public QObject
{
   Q_OBJECT
   Q_PROPERTY(QString model READ getModel WRITE setModel)      
public:
   explicit Vehicle(QObject *parent = 0);
   QString getModel() const;      
   void setModel(QString model);
   virtual QString toString() const;
private:
    QString _model;
};

Inherited Class:

class TransportVehicle : public Vehicle
{
    Q_PROPERTY(int Capacity READ getCapacity WRITE setCapacity)

public:
    TransportVehicle();
    TransportVehicle(int, QString, int);
    int getCapacity() const;
    void setCapacity(int);

    QString toString() const;
private:
    int _maxCapacity;
};

and the following snippet from a generic method to access the properties of which ever object it finds in the list that is passed to it:

int write(QObjectList* list) {
int count = 0;
for(int i = 0; i < list->size(); i++)
{
    const QMetaObject *mo = list->at(i)->metaObject();
    for(int k = mo->propertyOffset(); k < mo->propertyCount(); k++)
    {
        const QMetaProperty prop = mo->property(k);
        QString name = prop.name();
        QString valStr = prop.read(list->at(i)).toString();
        QDebug << name << ": " << valStr << endl; 
        count++;
    }
    delete mo;
}
return count;
}

It works fine except my output will be like 'model: toyota' and won't include capacity.

The only way I've been able to get the properties of my subclasses is to add virtual get and set methods and an additional Q_property to my base class, which doesn't seem right at all and not possible in normal circumstances where I don't have access to the base class.

Topher
  • 1,011
  • 11
  • 19
  • Why are you deleting mo? – dtech Mar 09 '16 at 18:42
  • @ddriver I did it while unsure, I thought since it's a pointer, since it's being redeclared in each iteration that I should clean up? Or is this unneeded completely because of it being a QObject? – Topher Mar 09 '16 at 20:26
  • Don't delete it, you are walking into undefined behavior. The pointer returned simply points to the meta object, it is not allocated dynamically and should not be deleted. – dtech Mar 09 '16 at 20:36
  • @ddriver Thanks for all your help. Much appreciated! – Topher Mar 09 '16 at 20:39

2 Answers2

0

You are missing use of macro Q_OBJECT:

class TransportVehicle : public Vehicle
{
    Q_OBJECT
    ^^^^^^^^
    Q_PROPERTY(int Capacity READ getCapacity WRITE setCapacity)

public:
    TransportVehicle();
    TransportVehicle(int, QString, int);
    int getCapacity() const;
    void setCapacity(int);

    QString toString() const;
private:
    int _maxCapacity;
};

For documentation please see : http://doc.qt.io/qt-5/qobject.html#Q_OBJECT

vcp
  • 962
  • 7
  • 15
  • I've added Q_GADGET, but it does the same, however I see the staticMetaObject as mentioned in the docs, but from looking at that while debugging I still only see the model property... any idea? – Topher Mar 09 '16 at 17:44
  • This is wrong, `Q_GADGET` is for when you want meta data but don't inherit `QObject`. – dtech Mar 09 '16 at 18:38
0

Vehicle inherits QObject, so TransportVehicle will have to use the Q_OBJECT macro, Q_GADGET is when you don't inherit QObject and want a meta object.

Every class which directly on indirectly inherits QObject needs the Q_OBJECT macro. You don't have it in TransportVehicle so you don't get meta data generated for it, you are stuck with the meta object that was generated for the base class.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • Ok, so I tried that initially but get a "undefined reference to 'vtable for TransportVehicle' error. Which as far as I remember, is a similar error like when trying to use Template classes, the inheriting class must be declared in the same file as the base class right? So is that the same case with QObject? I've tried it and it works but is that the only way? Or can one use something like forward class declarations rather? – Topher Mar 09 '16 at 20:14
  • @topher - try clean all, run qmake and rebuild all from the build menu – dtech Mar 09 '16 at 20:17
  • Awesome thanks that got it! Can't believe I spent hours on this because I needed to rebuild :) – Topher Mar 09 '16 at 20:19