Important: Please read the Qt Code of Conduct -

Subclassing QAbstractItemView in a complicated (?) way?

  • This is more of a "theoretical C++ question" than a deeply Qt-related one.

    I have a highly customized QTableView (a couple thousand lines of code) and I want to create another view class (probably QListView) that is just as customized and probably shares 99% of the code I already have.

    The perfect solution in this case seems to be to first subclass QAbstractItemView, add all my code, then derive QTableView etc. from that subclass. But since I am using Qt, I cannot easily do that, the heritage-chain is immutable. (I may be wrong, and actually hope to be.)

    Since I am overriding several virtual methods of QAbstractItemView (in my QTableView-subclass), I don't think that multiple inheritance would be a fitting solution. I need the interface of the resulting class (e.g. "MyTableView", "MyOtherView", ...) to stay as it is so the rest of the code continues to work nicely.

    Does anybody have an idea aside from the obvious (and extremely ugly) "just copy your code over to the new class"?

  • You can't alter the inheritance chain of the Qt classes (except for changing the source code of Qt of course).
    Since QTableView and QListView already inherit QAbstractItemView you can't inherit from QAbstractItemView in your class, because that would lead to the diamond inheritance problem that Qt doesn't support (two parents inheriting from QObject).

    What you can do though is have MyTableView and MyListView inheriting from QTableView and QListView respectfully and then also from another base class of yours, that would implement the common methods. You would need some boilerplate code in My* classes that would override the methods of QAbstractItemView and just call the implementation from the common base.
    That's still not perfect, but that code needs to be copy-pasted once and is simple enough(one-liners basically) that it wouldn't need to be looked at again, while the "real code" that needs maintaining would be kept in a single common class.

  • Hi,

    multiple inheritance is more than "would not be a fitting solution", it is impossible: it would make your class deriving twice from QObject -- once from QAbstractItemView, once from QTableView. I see 2 "not so bad" solutions: the first one is to forget about QTableView and QListView, and make your own view architecture. So you will be able to share a common parent for "MyTableView" and "MyListView", but you will have to reimplement all the specialized code. The other way is to use a template like the following:
    template<typename T>
    class MyAbstractItemView : public T
    // do your thousands lines of code here

    class MyTableView : public MyAbstractItemView<QTableView>

    class MyTableView : public MyAbstractItemView<QListView>

    The problem here is that you can't use the Q_OBJECT macro in a template class, you your base should not declare signals and slots.

    EDIT: or you have the solution of chrisaverage

  • I already read about the diamond-problem (and that virtual inheritance can help a bit), so that's a no-go. But writing my own views is, too - I think that QTableView etc. are pretty complex and I would basically need to copy their code instead of my own, which would be an even worse solution since I would have to check the Qt sources regularly to keep my own code up-to-date.

    Mixing in a completely unrelated class and using its methods for the overrides seems to be a somewhat decent solution. I guess I will have to go with that (the template method is worth a look, but I'll have to check my code since I probably need the Q_OBJECT macro).

    Thanks so far. :)

Log in to reply