> On 25 Feb 2026, at 08:44, Fabian Kosmale via Development 
> <[email protected]> wrote:
> 
> Hi,
> 
> 
>> Is it to change the setter/getter function? Would that not better be solved
> making the setter/getter virtual on the C++ side and removing the "overriden"
> property?
> 
> We intend to also add some more guidance when you want to do this to
> the docs, but in general your assessment is correct: if you can solve the
> issue at the C++ level, that's probably the better place.
> 
> We have however encountered a few cases where this is necessary, or the
> least bad solution:
> - turning a writable property read-only and vice-versa (the most prominent 
> example
>   being Item's implicitWidth). Removing writability is still fishy in my 
> opinion
>   (implicitWidth notwithstanding), but adding it in a subclass is arguably 
> fine from a
>   type theory point of view (as it's less restrictive).
> - changing the type of a property in a way not compatible with C++ 
> polymorphism
>  (used to be more important when we hadn't support for int64 at all in the 
> engine,
>   but in a base lib usable with Widgets, you might still want a
>   `std::optional<int>` property in the C++, but expose a QJSValue (which can 
> be
>   undefined under the same name to QML)
> - allowing the narrowing possible in C++ in QML, as in have a property that's 
> always
>  an Item in a C++ base, but guarantee that it's a Rectangle in a QML derived 
> type.
> 
> You might also have cases where you believe that shadowing is generally a 
> terrible idea,
> but where a search on open source repositories shows that tons of projects 
> have in fact
> shadowed it. In that case, you can mark the base property as virtual, which 
> causes an
> unconditional warning – and if those projects really intended to shadow it, 
> they can then
> add override, and it is fine(ish).
> 
> Kind regards,
> Fabian


Thanks Ulf for the heads-up and for the “foot archery” phrase :)

It's good to have the tools to make the intent explicit, so this is a good step 
in the right direction, especially if it allows us to warn about probably 
unwanted overrides while still giving people a way to turn off the warning in a 
controlled fashion.


We also have the Q_OVERRIDE macro. It is used extensively by QTextBrowser to 
override 3 properties, and…. nowhere else in Qt. Github knows of one more exact 
match in KDE/kommander.

Q_OVERRIDE allows (some) attributes of a base-class property to be redeclared. 
I.e. QTextEdit (as the base class of QTextBrowser) has a “readOnly” property 
that is DESIGNABLE and SCRIPTABLE (which is the default); QTextBrowser as a 
read-only viewer overrides that property to be neither DESIGNABLE nor 
SCRIPTABLE via

    Q_OVERRIDE(bool readOnly DESIGNABLE false SCRIPTABLE false)

So if you drop a QTextBrowser into the Qt Widget Designer, then the property 
editor will not list the readOnly property. That’s, if I remember correctly, 
the only reason why Q_OVERRIDE exists.

Some of the cases you list above, Fabian, seem similar, i.e. removing 
writability from a property by redeclaring it without WRITE method. Perhaps we 
don’t need both Q_OVERRIDE and OVERRIDE/VIRTUAL tagging.


Volker



> ________________________________________
> Von: Development <[email protected]> im Auftrag von Albert 
> Astals Cid <[email protected]>
> Gesendet: Dienstag, 24. Februar 2026 19:37
> An: [email protected]
> Betreff: Re: [Development] shadowing properties (and methods)
> 
> El dimarts, 24 de febrer del 2026, a les 15:57:39 (Hora estàndard d’Europa
> central), Ulf Hermann via Development va escriure:
>> Greetings and Salutations,
>> 
>> As some of you may know, QMetaObject has a problem with what we call
>> "shadowing". Consider:
>> 
>> class Base
>> {
>>     Q_OBJECT
>>     Q_PROPERTY(int a READ a CONSTANT)
>> 
>> public:
>>     int a() const { return 4; }
>> 
>>     Q_INVOKABLE int b() const { return 5; }
>> };
>> 
>> class Derived : public Base
>> {
>>     Q_OBJECT
>>     Q_PROPERTY(int a READ a CONSTANT) // shadows Base::a
>> 
>> public:
>>     int a() const { return 6; }
>> 
>>     // Shadows Base::b
>>     Q_INVOKABLE int b() const { return 7; }
>> };
>> 
>> Now when you get a Base* and retrieve its property "a" or call its
>> method "b" via the QMetaObject, you don't actually know which property
>> you are retrieving or which method you are calling.
>> 
>> From C++ you can introspect the QMetaObject hierarchy and determine
>> what property or method you're dealing with. This is much more
>> complicated than the usual way of simply doing
>> someObject->property("a"), though.
>> 
>> From QML, you can't. QML will always use the most-derived QMetaObject
>> that has the property or method. You can shadow properties and methods
>> further in QML, and most egregiously, you can shadow properties with
>> methods and vice versa. This is rather dangerous because we internally
>> rely on many of the properties of, say QQuickItem, to actually assume
>> the values we set on them. If you shadow a property like
>> QQuickItem::data, you're certainly in for some surprises. It is quite
>> common to add a property called "data" to one of your custom types,
>> though. So, this is inviting some serious foot archery. For fun and
>> confusion, try the following:
>> 
>> // Base.qml
>> import QtQuick
>> Item {
>>    id: root
>>    property int data
>> }
>> 
>> // Derived.qml
>> import QtQuick
>> Base{
>>    Rectangle {}
>> }
>> 
>> This results in the following warning:
>> 
>> Derived.qml:3:4: Cannot assign value of type "Rectangle" to property
>> "data", expecting "int"
>> 
>> We've recognized this as a problem a long time ago and introduced the
>> FINAL attribute to Q_PROPERTY. The FINAL attribute only takes effect if
>> you use QML. If you shadow a FINAL property in pure C++, it does nothing
>> (unfortunately). However, if you try to use a *shadowed* FINAL property
>> in QML you get a warning or an error, depending on the context. We can't
>> really do better than this for FINAL alone. You can call moc on Base and
>> Derived independently, and you can re-moc Base after building Derived.
>> This way you can sneakily introduce a FINAL after the derived type
>> already exists. So we have to accept some fuzziness there. It follows
>> that also in QML we can't flat out reject all your shadowed properties.
>> We can just assume they are not shadowed and still use the base type's
>> properties in case they are.
>> 
>> On top of all this complication, however, the presence of FINAL is not
>> quite enough because you have to remember to add FINAL to every property
>> that's eligible for finality. Keeping track of this is messy and
>> error-prone. As a result, few properties are FINAL in practice, even if
>> most should be.
>> 
>> C++, back in the day, had a similar problem with virtual methods. When
>> you declared a method in a derived type, you'd have to look up all the
>> methods in all base types to figure out if the method you were declaring
>> was virtual by inheritance. This was error-prone. You could accidentally
>> introduce overriding methods that weren't meant to be virtual and vice
>> versa.
>> 
>> In C++, this was solved by introducing the "override" and "final"
>> keywords to mark methods that are intentionally overriding a virtual
>> one. The introduction of the "override" and "final" keywords came with a
>> number of warnings and errors that now steer you towards adding the new
>> keywords to all methods that intentionally override, and only those.
>> 
>> In Qt 6.11, we're doing the same to Q_PROPERTY. In addition to FINAL,
>> you can now add attributes VIRTUAL and OVERRIDE to mark properties that
>> are intended to be overridden and ones that intentionally override a
>> virtual property.
> 
> Can you give an example of why one would want a virtual/override property?
> 
> Is it to change the setter/getter function? Would that not better be solved
> making the setter/getter virtual on the C++ side and removing the "overriden"
> property?
> 
> Cheers,
>  Albert
> 
>> Likewise, in QML you can mark properties with the
>> "virtual", "override", and "final" keywords. If you use those new
>> attributes and keywords, you get appropriate warnings and errors in QML
>> (but not in C++, because see above). If you don't use them, you don't
>> get warned ... yet. This is because we haven't adapted all of Qt to be
>> free of those warnings, yet.
>> 
>> We still highly recommend you clean up unintended shadowing and use the
>> new keywords and attributes where applicable already in Qt 6.11. You can
>> get warned about shadowing properties without the new keywords and
>> attributes by enabling debug messages from the
>> qt.qml.propertyCache.append logging category. For example with an
>> environment variable like this:
>> 
>> QT_LOGGING_RULES="qt.qml.propertyCache.append.debug=true"
>> 
>> For Qt 6.12, we are planning to enable these warnings by default. Among
>> other things, this will mean that you will get warned when shadowing
>> properties from Qt types that aren't meant to be shadowed.
>> 
>> In addition, we are planning to resolve the issue of shadowing methods
>> and shadowing properties with methods in a similar way. We don't know
>> when this will be ready, though.
>> 
>> best regards,
>> Ulf
> 
> 
> 
> 
> --
> Development mailing list
> [email protected]
> https://lists.qt-project.org/listinfo/development
> -- 
> Development mailing list
> [email protected]
> https://lists.qt-project.org/listinfo/development

-- 
Development mailing list
[email protected]
https://lists.qt-project.org/listinfo/development

Reply via email to