0

私は現在、さまざまな方法で実装できる汎用の「コレクション」インターフェイスを定義したいプロジェクトに取り組んでいます。コレクション インターフェイスは、値によって反復子を返すメソッドがコレクションにあることを指定する必要があります。ポインターをラップするクラスを使用して、次のように思いつきました (大幅に簡略化されています)。

Collection.h

class Collection
{
    CollectionBase *d_base;
public:
    Collection(CollectionBase *base);

    Iterator begin() const;
};

inline Iterator Collection::begin() const
{
    return d_base->begin();
}

CollectionBase.h

class CollectionBase
{
public:
    virtual Iterator begin() const = 0;
    virtual Iterator end() const = 0;
};

Iterator.h

class Iterator
{
    IteratorBase *d_base;
public:
    bool operator!=(Iterator const &other) const;
};

inline bool Iterator::operator!=(Iterator const &other) const
{
    return d_base->operator!=(*other.d_base);
}

IteratorBase.h

class IteratorBase
{
public:
    virtual bool operator!=(IteratorBase const &other) const = 0;
};

この設計を使用すると、 コレクションのさまざまな実装が から派生し、の特定の実装をラップCollectionBaseする を返すことによって、カスタム イテレータを返すことができます。IteratorIteratorBase

これまでのところ、すべてが順調でダンディです。私は現在、実装方法を理解しようとしてoperator!=います。Iteratorに呼び出しを転送しますがIteratorBase、そこでオペレーターをどのように実装する必要がありますか? IteratorBase簡単な方法の 1 つは、 の実装で参照を適切な型にキャストし、IteratorBaseの実装に対して特定の比較を実行することですIteratorBase。ただし、これは、2 つの異なるタイプのイテレータを渡さずに適切にプレイすることを前提としています。

もう 1 つの方法は、反復子が同じ型であるかどうかをチェックする何らかのタイプのチェックを実行することです。ただし、このチェックは実行時に行う必要があると思います。これがイテレータであることを考えると、コストのかかる実行時の型チェックを実行したくありませんoperator!=

ここでより良い解決策がありませんか?おそらく、より優れた代替クラス設計があるでしょうか (現在の設計は、私が受講している C++ コースで学んだことから適応したものです)。これにどのようにアプローチしますか?

編集: STL コンテナーを教えてくれたすべての人に: 私はその存在を認識しています。ただし、処理する必要があるデータの量が膨大になることが多いため、すべての場合にこれらを使用できるわけではありません。ここでのアイデアは、メモリではなくストレージとしてディスクを使用する単純なコンテナーを実装することです。

4

4 に答える 4

4

これは、C++ を使用する方法ではありません。std::vector や std::map などの標準ライブラリ コンテナー クラスと、テンプレートの使用について調査することを強くお勧めします。継承は、常に最後の手段の設計ツールであるべきです。

于 2009-12-11T11:52:47.313 に答える
2

コンテナを実行するSTLの方法を模倣してください。そうすれば、例えば<algorithm>あなたのコンテナで使用することが可能になるでしょう。

于 2009-12-11T12:03:06.250 に答える
1

イテレータに継承を使用する場合は、STL とは異なるアプローチを使用することをお勧めしますbegin()/end()

IEnumeratorたとえば、.NET フレームワークから見てみましょう。( MSDN ドキュメント)

基本クラスは次のようになります。

class CollectionBase
{
    // ... 
    virtual IteratorBase* createIterator() const = 0;
};

class IteratorBase
{
public:
    virtual bool isEnd() const = 0;
    virtual void next() const = 0;
};

// usage:
for (std::auto_ptr<IteratorBase> it = collection.createIterator(); !it->isEnd(); it->next)
    {
    // do something
    }   

にとどまりたい場合はbegin()/end()、 を使用dynamic_castして、適切なタイプがあることを確認できます。

class MyIteratorBaseImpl
{
public:
    virtual bool operator!=(IteratorBase const &other) const
    {
       MyIteratorBaseImpl * other2 = dynamic_cast<MyIteratorBaseImpl*>(&other);
       if (!other2)
          return false; // other is not of our type

       // now you can compare to other2
    }
}
于 2009-12-11T11:47:07.663 に答える
0

イテレータに仮想 'entiy-id' 関数を追加し、演算子で!= チェック this->entity_id () および other.entity_id () (私の例では、'position' 関数はそのような 'entity-id' 関数です)。

于 2009-12-11T11:35:04.797 に答える