[SOLVED] Order in Dual Inheritance - QList and QObject
-
I created a list that emits a signal objectAdded() whenever a new object is added to the list. My class inherits from QList (for all the list functionality) and from QObject (for all the signal/slot functionality) as follows:
@class MyList : public QList<MyObject*>, public QObject
{ … }@When I compiled it, I got some errors complaining about not being able to find QMetaObject stuff. So I immediately thought it had something to do with inheriting from QObject. So I changed my order of inheritance as follows in order for it to work:
@class MyList : public QObject, public QList<MyObject*>
{ … }@My question: why does the order of inheritance matter? Can’t the compiler automatically pick up that QList is not inheriting from QObject and therefore has to look in the second inheritance?
-
The usual practice is to aggregate collections, not inherit them. Also it is usual practice to put QObject at the bottom of inheritance.
Also, judging from the lack of a virtual destructor for QList, it doesn't look like it was intended to be inherited to begin with. IIRC this is called a "concrete class"
-
The problem with aggregation/composition is that you have to implement all the functions you need. With inheritance, all functions are already there.
You mentioned that you normally put QObject at the end of inheritance, so why didn't that work.
Even though there is no virtual destructor, QQueue still inherits from QList, so either the Qt developers did something wrong, or QList is meant to be inherited. -
This is an issue with the MOC tool: http://qt-project.org/doc/moc.html#multiple-inheritance-requires-qobject-to-be-first
MOC has a few issues, mostly coming down to the fact that C++ code can be complex, and MOC is only able to interpret relatively simple forms of class declarations. -
Thanks Terence. Will there be a "fix" in the future, or is this just a thing we have to live with?
-
By bottom I mean first, as you probably are aware, QObject is the base class for most other Qt classes, base implies bottom - that much should be clear.
The lack of a virtual constructor on itself may not be fatal at all, so long as you don't use polymorphism and deeper hierarchies. As for the functionality, you can simply create a wrapper for the aggregated container, it will add minimal to virtual no cost to the performance of your class.
The programmers of Qt are far more familiar with the internal structure of Qt, just because they can afford to do something doesn't mean everyone shoul. As I said, it may not be a problem at all, but eventually it may end up in some kind of undefined behavior, which can result in everything from nothing to a program crash.
-
[quote author="goocreations" date="1348211986"]The problem with aggregation/composition is that you have to implement all the functions you need. With inheritance, all functions are already there. [/quote]
Well, true to a point, but to do anything interesting, you will need to reimplement these methods anyway, for instance to send your signals. And that's when it hits you: they are not even virtual! For instance, if you want to send a signal when an item is added to the list, you will need to reimplement append and insert (in their various forms). You can't, as they are not virtual.
[quote]You mentioned that you normally put QObject at the end of inheritance, so why didn't that work.[/quote]
No, that's not what was said. Please re-read the comment.
[quote]
Even though there is no virtual destructor, QQueue still inherits from QList, so either the Qt developers did something wrong, or QList is meant to be inherited.
[/quote]You can in principle inherit from classes without a virtual destructor, but it takes special care doing so. Mostly you need to take care not to add any new class members. In the case of QQueue (and yes, also QStack), all that is done is add some syntactic sugar. There are only functions that form a thin layer over existing functionality in the underlying class. However, when you inherit like you are, and someone destructs the class via a QList* pointer to it, you whole QObject part of the object will not be destructed. So, the rule of thumb is: don't, unless you know what you are doing. Pointing to somebody else doing it too does not count as knowing what you are doing.
-
[quote author="goocreations" date="1348212389"]Thanks Terence. Will there be a "fix" in the future, or is this just a thing we have to live with?[/quote]
I have not heard of efforts to fix it, but I can imagine that at one time it will be. There have been advances in compiler technology and code analysis that might find their way into moc too. Don't hold your breath though.