On Friday 24 March 2017 11:34:37 Edward Welbourne wrote: > Marc Mutz (23 March 2017 20:41) > > > 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). > > well, I - for one - can only see a minor problem; so, since you *have* > mentioned it, perhaps you could elaborate ? I hadn't realised QVector > wasn't public - I can see how that would be an argument for the > inheritance to be private. Is there more to the problem than that ? > You make it sound a bigger deal than anything I can see in the source - > so please educate me,
Well, where should I start? There are two principles that interact to cause all kinds of mayhem, both of them on Windows: 1. When a class is exported, all of its members are exported. That includes the base class' members, regsardless of whether they were exported themselves or not. 2. When an inline function is exported (by itself or via a class-level export), MSVC calls the copy in the DLL. I don't know whether it places a copy in the user's executable at all. You can prevent this behaviour by marking each such function with Q_ALWAYS_INLINE. (2) means we can't change signatures of exported inline functions, because that would be BiC on Windows/Debug. On all other platforms, incl. Windows/Release, renaming, removing, changing the signature of, an inline function, exported or not, is always BC. It may be SiC, but it's always BC. We have many use-cases that assume that inline functions do not form part of the ABI: a. QVector and other container change the signature of begin() etc to implement QT_STRICT_ITERATORS. As a consequence, QT_STRICT_ITERATORS fails for (at least) QXmlStreamAttributes, inheriting QVector, because only one of the two overloaded functions gets exported while the other one is not. You may disregard this as a container-only thing, but it's far more widespread: b. We also assume we can #if Q_COMPILER away functions as long as they are inline. You see where this is going? Once MS actually keeps BC themselves, and afaiu, they plan to do so for 2015 -> 2017, this will cause BiC in all exported classes whenever 2015 lacks a feature that 2017 provides. I don't know why Thiago thinks these reasons are not worth stopping exporting non-polymorphic classes for, but I'm absolutely convinced that exporting only non-inline functions in such classes is the only correct way to deal with the Microsoft platform. Non-polymophic classes should decide what they want to be: I. if they want to be pimpl'ed, they should have most functions out-of-line. In this case, it's ok to export the whole class, but all inline functions should have to be marked as Q_ALWAYS_INLINE from the outset. II. if they want to be thin abstractions, most functions should be inline. The class should not be exported, only out-of-line functions should be. To prevent inheriting such classes, thereby exporting their inline functions, such classes should be agressively marked as final. Polymophic classes should follow the rules of (I) (class-level exporting them is required here) plus have all their virtuals (incl. esp. their dtor) defined out-of-line. HTH, Marc -- Marc Mutz <[email protected]> | Senior Software Engineer KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company Tel: +49-30-521325470 KDAB - The Qt, C++ and OpenGL Experts _______________________________________________ Development mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/development
