バックグラウンド:
ObjectListModel
を継承QAbstractListModel
して含むクラスを呼び出していQObjectList
ます。オブジェクトは行で、そのプロパティは列 ( を使用して設定QMetaObject
) であり、通知の変更はビューに伝達されます。また、いくつかのコンテナ ヘルパー (begin/end/iterator/size) もあるので、格納されている QObject を反復処理できます。- タイプセーフを提供するも持っています (主にet.al. を
TypedObjectListModel<T>
オーバーライドし、Tに対して行う新しいタイプを定義することによって)。push_back
iterator
static_cast
オブジェクトのタイプが 1 つしかない場合、これはすべて非常にうまく機能します。新しいクラスを作成するだけです (f.ex.FruitsModel
が含まれQ_OBJECT
、継承しTypedObjectListModel<Fruit>
ます。これには、Fruits または Fruit-subobjects のみを含めることができます。
ただし、2 つの異なる状態で実行できるアプリがあります。2 番目の状態では、モデルはリンゴのみを保持し、バナナ (具体的な基底クラスである果物) は保持しません。
ApplesModel
したがって、T の型を継承して変更する必要がある型を作成したいと思います。継承ダイヤモンドOF DEATHFruitsModel
を取得するため、これにより問題が発生します。
QObject
|
QAbstractListModel
|
ObjectListModel -------------------
| |
TypedObjectListModel<Fruit> TypedObjectListModel<Apple>
| |
FruitsModel -------------------ApplesModel
FruitsModel::push_back(Fruit*) は ApplesModel では違法であるため、これも概念的に間違っています。ただし、果物 (リンゴだけでなく) の読み取り/反復は可能である必要があります。
また、FruitsModel ( findFruitById
) には、オーバーライドして ApplesModel でのみ Apple を返す必要がある関数がいくつかあります。
C++ でこの問題を解決する際に推奨される設計パターンは何ですか?
似たようなことを試みたのは私が初めてではないと思います (希望します)。
私は多くのアイデアを試しましたが、さまざまな行き止まりに行き詰まっています。ObjectListModel の仮想継承が問題を解決すると思うかもしれませんが、私はこれを使用して取得しQObject::findChild
ます:
error C2635: cannot convert a 'QObject*' to a 'ApplesModel*'; conversion from a virtual base class is implied
上記は、代わりに dynamic_cast を使用して、findChild の独自の実装で修正できますが、まだいくつかの行き止まりがあります。
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 を気にしないのと同じ欠点。