[Development] QList
Marc Mutz
marc.mutz at kdab.com
Thu Mar 23 22:12:23 CET 2017
On Thursday 23 March 2017 21:16:55 Thiago Macieira wrote:
> On quinta-feira, 23 de março de 2017 12:41:56 PDT Marc Mutz wrote:
> > On 2017-03-23 19:27, Thiago Macieira wrote:
> > > In the mean time: why do you care if some class derives from
> > > QStringView?
> >
> > Because it's _wrong_.
> >
> > It does not model is-a, so public inheritance is out of the question.
>
> I beg to differ. It *is* "is-a": any modifiable QString is also a view to
> itself.
"is-a" is a terminus technicus. It means is-subtype-of aka.
https://en.wikipedia.org/wiki/Liskov_substitution_principle
> Also, remember the point that it would be a private base, so the is-a
> relationship is not visible. This is about code reuse, not about the
> semantic.
If it's private inheritance, it's not is-a.
> > QString cannot use a lot of QStringView functions (like mid()) without
> > changing at least the return type, so inherit-to-reuse-implementation is
> > also not valid.
>
> For some cases, that's true, but only because functions like mid() try to
> return *this if they detect that there's no change. That's an optimisation
> inside QString, not a requirement of the interface.
>
> A naïve implementation of QString::mid() could be:
>
> QString QString::mid(int start, int len) const
> {
> return QString(QStringView::mid(start, len));
> }
Which is no different from
return QString(QStringView(*this).mid(start, len));
so does not provide a case supporting using inhertance.
> > Last, there are no virtual functions in QStringView that QString would
> > want to reimplement.
>
> Virtual has nothing to do with anything. QString is complementing
> QStringView, only adding functionality.
I'm merely listing the use-cases for inheritance. Good that you agree that
none appy :)
> > So, of the three use-cases for inheritance, none are relevant here, so
> > it follows that inheritance is not the tool to use. You may consider
> > composition, though, as I said, I'd rather provide free functions that
> > most QString/View methods forward to than picking one class and calling
> > its methods from all others.
>
> From a strict theoretical point of view, that might be better.
>
> From the practical point of view, implementing something as simple as
>
> int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
> {
> return QStringView(*this).indexOf(c, from, cs);
> }
I said it many time, and I'll say it once more: The way to share code is
through free functions, not one class delegating to another:
return qFindChar(*this, ch, from, cs);
or
return qFindString(*this, QStringView(&ch, 1), from, cs);
where only the qFoo() functions are exported, but none of the QString/View/Ref
members.
> means:
> 1) we have an extra entry point in the library
> 2) so more symbols in the symbol table, increasing the chances of hash
> collision
> 3) more code that, at best, inlines QStringView::indexOf into the new
> function. That is, the best we can hope for is that the compiler turns
> the above into:
>
> int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
> {
> return findChar(unicode(), length(), ch, from, cs);
> }
>
> Also note we'd probably want to mark findChar as Q_NEVER_INLINE so that the
> compiler doesn't expand the same function twice, which would mean an even
> bigger QtCore.
Note how all of those concerns are addressed by qCompareStrings()-like
delegation to free functions.
> > > We certainly need to discuss the presence of an extra pointer inside,
> > > as that
> > > has a cost. But derivation?
> >
> > Derivation is the strongest coupling mechanism in C++, after friendship.
> > Do I need to mention QPolygon and what pain it's inheritance from
> > QVector<QPoint> has caused? (FTR: cf. end of qvector.h and
> > qvector_msvc.cpp).
>
> Because MSVC ABI, like the Windows ABI, has severe shortcomings and
> actually violate the C and C++ standards. Some of them are legacy reasons
> from the 1980s, like the one causing crashes reported in QTBUG-38876
> (attempt for Qt 6 fix at https://codereview.qt-project.org/189193 ).
I'm merely pointing out that inheriting one value class from another, even
publicly (but the same problem would exist with private inheritance, I
guess?), has already caused much pain. We should learn from it two things:
1. not inhert one value type from another
2. not class-level-export value classes, only export out-of-line functions
Thanks,
Marc
--
Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt, C++ and OpenGL Experts
More information about the Development
mailing list