1

コードで std::map を使用してデータを保存しています。マップの反復子を使用して要素にアクセスしたり変更したりするのは非常に簡単ですが、いくつかの操作 (++、[] など) を実際に抑制する必要があるため、それが正しいかどうかはわかりませんが、ほとんどないようです。記事では std::map を直接継承しないことを推奨しているため、代わりにラッパーを作成しています。

class MyContainer
{
  private:
    std::map<int, int> data;

  public:
    int &operator[](int); // here we write the interface to control the behavior of accessing the data element
    void &operator++();
    void &operator--();
};

しかし、これは別の問題を引き起こします。実際、要素にアクセス/変更するために、コードのいたるところでイテレータを使用しています。しかし、マップが自己定義クラスに移動した後は、メイン プログラムでイテレータを使用してデータを処理できなくなりました。独自のイテレータを作成することを推奨する人がいますが、いくつかの記事を読んだ後、std::iterator を継承して独自のイテレータをカスタマイズすることを提案しているようです。それは簡単に思えますが、それでも私には抽象的すぎます。2つの疑問があります

1) マップを繰り返しますが、ラッパーは実際にはコンテナーではありません。また、マップ要素に対する次の操作 (++、-、[]) の動作を制御するには、マップの代わりに MyContainer を参照する自己定義イテレータを用意する必要があります。マップを進める必要があるため、混乱しているように思えますが、イテレータは代わりにラッパーを参照します。私はそれを機能させる方法がわかりません。同様のケースで従うことができる例はありますか? ありがとう。

2) コードでマップ要素に直接アクセスしたくないので、ラッパーで演算子を次のように定義しました。

int &operator[](int)

上記の関数では、返される参照は入力パラメーターに依存します。つまり、場合によっては、要素を参照する代わりに NULL 参照を返す可能性があります。ただし、NULL が返された場合、次の呼び出しは無効になります。

data[3]++;

data[3] は null 参照を返す可能性があるためです。しかし、要素を更新する前に、返された参照が null かどうかを確認するにはどうすればよいでしょうか?

4

2 に答える 2

2

++要素の演算子などに特別な動作を実装するのはやり過ぎだと思います。イテレータのインクリメントおよびデクリメント操作についても同様です。[]適切な解決策は、アクセサーに境界チェックを追加し、必要に応じて範囲外の例外をスローすることだと思います。したがって、マップのbegin()およびend()メソッドを使用して、境界チェックを に追加し[]ます。

class MyContainer
{
  private:
    std::map<int, int> data;
  public:
    typedef std::map<int, int> MapType;
    typedef MapType::iterator iterator;
    typedef MapType::const_iterator const_iterator;
    typedef MapType::reference reference;
  public:
    iterator begin() {return data.begin();}
    const_iterator begin() const { return data.begin();}
    // and so on ...
    reference operator[](size_t i) {
      if (data.size()<=i) { /* raise exception here */ }
      return data[i];
    }
    const reference operator[](int) const { /* same as above */}

};

これには、戻り値の型が標準ライブラリ コンテナーの型と一致するという利点があります。

于 2012-04-19T08:26:20.793 に答える
0

反復する必要がある場合は、「マップ」を公開することができます。それ以外の場合は、反復のインターフェイスを提供せず、(反復が必要な) すべてを内部で行います。

于 2012-04-19T08:54:30.913 に答える