6

私は以下のようなクラスを持っています:

class Foo {
private:
    std::map<std::string, Bar*> bars_by_name;
    std::map<std::string, Baz*> bazs_by_name;
};

ここで、ユーザーが両方のコレクションにアクセスできるようにしますが、オブジェクトをstd::mapsに格納している実装の詳細を非表示にします。代わりに、BarとBazは同じクラス階層に属しているため、コレクションの定数イテレーターや、場合によっては両方のコレクションからオブジェクトを返すカスタムイテレーターを返すメンバー関数が必要です。スタイルを考えると、C ++でこれを行う適切な方法は何でしょうか?Javaでは、おそらくメソッドの戻り型をIterableに設定するか、コレクションをunmodizableCollectionにラップします。

4

2 に答える 2

1

コレクションのイテレータを自分のものとして渡すことができます。

class Foo {
  private:
    typedef std::map<std::string, Bar*> BarContainer;
    typedef std::map<std::string, Baz*> BazContainer;
  public:
    typedef BarContainer::const_iterator ConstBarIterator;
    ConstBarIterator beginBars() { return bars_by_name.cbegin(); }
    ConstBarIterator endBars()   { return bars_by_name.cend(); }
    typedef BazContainer::const_iterator ConstBazIterator;
    ConstBazIterator beginBazs() { return bazs_by_name.cbegin(); }
    ConstBazIterator endBazs()   { return bazs_by_name.cend(); }

  private:
    BarContainer bars_by_name;
    BazContainer bazs_by_name;
};

これにより、独自のイテレータを実装する手間が省けますが、後でコンテナタイプを変更し、呼び出し元に再コンパイルするだけで済むという柔軟性が残ります。

両方を一緒に繰り返すという問題は解決しません。

于 2012-06-19T23:40:25.237 に答える
1

詳細を非表示にするインターフェースを作成します。

class Foo {
    public:
        void AddBar(std::string name, Bar*);
        void RemoveBar(std::string name);

        Bar* GetBar(std::string name);
        Bar* GetBar(std::string name) const;

        void AddBaz(std::string name, Baz*);
        void RemoveBaz(std::string name);

        Baz* GetBaz(std::string name);
        Baz* GetBaz(std::string name) const;

    private:
        std::map<std::string, Bar*> bars_by_name;
        std::map<std::string, Baz*> bazs_by_name;
};

すべてのユーザーが知っていることですが、リスト内、ベクトル内、または並列配列を使用して、std::pairにそれらを格納することができます...実際には何でも。

編集:

あなたがそれを地図に保存しているが、ユーザーに下にあるコンテナを繰り返してもらいたいという事実は、悪い/間違ったデザインのにおいがします。上記のように個別のアクセスのみを許可するか、これを行うメソッドを作成します。

于 2012-06-19T23:11:20.620 に答える