背景:
- 我有我的类
ObjectListModel
,它继承QAbstractListModel
并包含一个QObjectList
. 对象是行,它们的属性是列(使用 a 设置QMetaObject
),并且通知更改会传播到视图。还有一些容器助手(开始/结束/迭代器/大小),以便我可以遍历存储的 QObject。 - 我也有一个
TypedObjectListModel<T>
,它提供类型安全(主要是通过覆盖push_back
et.al. 并定义对 T起作用的新iterator
类型)。static_cast
当我只有一种类型的对象时,这一切都很好。我只是创建新类 (f.ex. FruitsModel
,其中包含Q_OBJECT
并继承TypedObjectListModel<Fruit>
。这只能包含 Fruits 或 Fruit-subobjects。
但是,我现在有一个可以在两种不同状态下运行的应用程序。在第二种状态下,模型应该只包含 Apples,而不是 Bananas(或 Fruits,这是一个具体的基类)。
所以,我想创建一个ApplesModel
类型,它应该继承FruitsModel
并只是改变 T 的类型。这让我遇到了麻烦,因为我得到了继承钻石OF DEATH:
QObject
|
QAbstractListModel
|
ObjectListModel -------------------
| |
TypedObjectListModel<Fruit> TypedObjectListModel<Apple>
| |
FruitsModel -------------------ApplesModel
这在概念上也是错误的,因为 FruitsModel::push_back(Fruit*) 在 ApplesModel 中是非法的。但是,应该可以读取/迭代 Fruits(不仅仅是 Apples)。
此外,我在 FruitsModel ( findFruitById
) 中有一些函数应该被覆盖,并且只返回 ApplesModel 中的 Apples。
在 C++ 中解决这个问题的首选设计模式是什么?
我怀疑(希望)我不是第一个尝试做类似事情的人。
我尝试了很多想法,但我陷入了各种死胡同。你会认为 ObjectListModel 的虚拟继承可以解决这个问题,但后来我得到了这个QObject::findChild
:
error C2635: cannot convert a 'QObject*' to a 'ApplesModel*'; conversion from a virtual base class is implied
上述问题可以通过我自己的 findChild 实现来解决,改用 dynamic_cast,但仍有一些死胡同。
template<typename T>
inline T myFindChild(const QObject *parent, const QString &name = QString())
{
return dynamic_cast<T>(qt_qFindChild_helper(parent, name, reinterpret_cast<T>(0)->staticMetaObject));
}
更新
geekp 有以下建议:
从 Fruit 继承 Apple 不打扰 ApplesModel
然后我如何强制只有苹果在 FruitsModel 中?另外,每次我拿一个苹果(作为水果)时,我都需要沮丧。
不要从 FruitsModel 继承(如果你不使用它的方法,你为什么要这样做?)
我正在使用一些方法,尤其是那些用于阅读的方法。
不要从 Apple 的 TypesObjectListModel 继承,只继承 FruitsModel。
与不使用 AppleModel 的缺点相同。