Does QT use dynamic_cast for QML properties?

Viewed 180

I came across curious behavior in QT.

Lets say you have a base controller:

class BaseController : public QObject
{
    Q_OBJECT

public:
    BaseController() = default

protected:
    inline BaseNode * getRoot() const noexcept { return root; }

protected:
    BaseNode * root;
};

And ExtraController:

class ExtraController final : public BaseController
{
    Q_OBJECT

    Q_PROPERTY( BaseNode * root READ getRoot NOTIFY changed )

public:
    ExtraController() { root = new ExtraNode(); }

signals:
    void changed();
};

Key moment, there is a two type of nodes. BaseNode simply an abstract class with property "id". ExtraNode is heir of BaseNode and has property "name".

Inside qml I use something like:

Label {
    text: extraController.root.name // property root - calls getRoot() in BaseController
}

And its works! Despite the fact that function getRoot() of a BaseController returns pointer to a BaseNode, which doesn't have "name" property. Question is: How does it work? How can I use properties of derived class in qml? Does qt perform dynamic_cast or so?

1 Answers

Qt uses its own meta object system. That is why you need MOC and the Q_OBJECT macro. So Qt "knows" which properties each object has during runtime and uses that knowledge for QML as well.

On the C++ side you can see this through QObject::property():

Returns the value of the object's name property. If no such property exists, the returned variant is invalid. Information about all available properties is provided through the metaObject() and dynamicPropertyNames().

Note that the properties an object has are independent of its type (see above reference to dynamic properties). The type of an object reference/pointer doesn't matter when accessing the object's properties - the correct meta object and list of properties will always be retrieved.

There is also a qobject_cast that makes use of the meta object system to downcast objects.

Related