我读了一些与此问题相关的其他线程,但没有为我的问题提供解决方案。我希望你们能给我一些想法或意见。
我正在尝试实现名为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
是非const 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;
}
};
//..
}
答案 0 :(得分:7)
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
得到指针。
答案 1 :(得分:0)
如果您要定义msi
const Map<std::string,int> msi;
而不是
Map<std::string,int> msi;
将调用const()和end()的const版本