非 const クラスの const_iterator を呼び出すにはどうすればよいですか?[重複]
質問
この問題に関連する他のスレッドをいくつか読みましたが、私の問題の解決策は提供されていませんでした。皆さんからアイデアやアドバイスをいただければ幸いです。
この名前のクラスを実装しようとしています 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
宣言されています protected
で const_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 バージョンが呼び出されます