非 const クラスの const_iterator を呼び出すにはどうすればよいですか?[重複]

StackOverflow https://stackoverflow.com//questions/21017654

  •  21-12-2019
  •  | 
  •  

質問

この問題に関連する他のスレッドをいくつか読みましたが、私の問題の解決策は提供されていませんでした。皆さんからアイデアやアドバイスをいただければ幸いです。

この名前のクラスを実装しようとしています Map. 。2つのイテレータが含まれている必要があります - iterator そして const_iterator.

それらを実装しました - iterator から継承します const_iterator, 、そして、 Map クラスには次の関数があります。

iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;

実装に何が必要かを確認するためにサンプル ファイルが与えられました。そこには次のコードがあります。

Map<std::string,int> msi;

...

// print map
for(Map<std::string,int>::const_iterator it = msi.begin(); it != msi.end(); ++it) {
// more stuff here
}

以来 msi 非定数 Map インスタンスです。 msi.begin() に電話をかける iterator begin() そしてそうではありません const_iterator begin() const, 、意図しない動作が発生します。

サンプルファイルが問題ないと仮定すると、どうすればそうできますか msi.begin() 正しいと呼びます const_iterator 関数?(それを考慮すると、反復子は次の型です const_iterator).

編集:自動変換についての話ですが、イテレータクラスを追加することにしました。私の間違いを指摘してください。

class Map {

    //...

    public:

        class const_iterator {

        private:

            Node* currNode;

        public:


            const_iterator(Node* cur_node = NULL) : currNode(cur_node) {}

            const_iterator& operator++() {
                currNode = currNode->next;
                return *this;
            }

            const_iterator operator++(int) {
                const_iterator old = *this;
                ++(*this);
                return old;
            }

            bool operator!=(const_iterator const& curr) {

                return !(*this == curr);
            }

            string operator*() {
                // this might cause memory leak
                string toString(this->currNode->key);
                std::stringstream s;
                int tmp = this->currNode->value;
                s << tmp;
                string secondString(s.str());
                toString = toString + ":" + secondString;
                return toString;
            }

            bool operator==(const_iterator const& curr) {
                return this->currNode == curr.currNode;
            }


            void operator=(const_iterator target) {
                this = target;
            }

            //void operator=(Node* target) {
            //    this->currNode = target;
            //}
        };

        class iterator : public const_iterator {

        private:

            Node* currNode;

        public:

            iterator(Node* cur_node = NULL) : currNode(cur_node) {}

            iterator& operator++() {
                currNode = currNode->next;
                return *this;
            }

            iterator operator++(int) {
                iterator old = *this;
                ++(*this);
                return old;
            }

            bool operator==(iterator const& curr) {
                return *this == curr;
            }

            bool operator!=(iterator const& curr) {

                return !(*this == curr);
            }

            string operator*() {
                // this might cause memory leak
                string toString(this->currNode->key);
                std::stringstream s;
                int tmp = this->currNode->value;
                s << tmp;
                string secondString(s.str());
                toString = toString + ":" + secondString;
                return toString;
            }

            void operator=(iterator target) {
                this = target;
            }

        };

        //..
}
役に立ちましたか?

解決

C++11標準コンテナの追加 cbegin そして cend その目的のために。それがなければ、いつでもオブジェクトをキャストできます。 const& 明示的に取得するには const オブジェクトの見方。

しかし、より根本的には、あなたの iterator への自動変換をサポートすべきではありません const_iterator. 。このように、クライアント コードを変更する必要はまったくありません。実際、あなたが言ったように、コードはすでにこれをサポートしているはずです。 iterator から継承します const_iterator.

ただし、投稿したコードにはいくつかのエラーが含まれています。まず、 operator= は間違っており、それに対するエラーが表示されるはずです。修正されたバージョンは次のとおりです。

void operator=(const_iterator target) {
    currNode = target.currNode;
}

さらに重要なのは、継承には意味がありません。本当だよ、あなた する 継承する iterator から const_iterator しかし、あなたのコードはこれが起こらなかったかのように振る舞う – iterator 親クラスを完全に再実装しており、親クラスとはまったく関係ありません。

iterator むしろ次のようになります:

class iterator : public const_iterator {
public:
    iterator(Node* cur_node = NULL) : const_iterator(cur_node) {}
};

もちろんこれには次のことが必要です currNode 宣言されています protectedconst_iterator. 。このクラスもまったく役に立ちません (ただし、現時点ではあなたのクラスも同様です)。 const_iterator クラス。実装する必要があります operator* これにより、その値を変更できるようになります。現在のコードでは、マップ値への参照 (に似たもの) ではなく、新しく作成された文字列を返すため、基本的にこれは許可されていません。

さらに、どのようにして const_iterator クラスは非を把握しますconst Node そもそもポインタ。それは不可能であるはずです:結局のところ、ポインタを const Map.

他のヒント

msi を定義する場合

const Map<std::string,int> msi;

の代わりに

Map<std::string,int> msi;

begin() と end() の const バージョンが呼び出されます

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top