I read some other threads related to this issue but non offered a solution for my problem. I hope you guys can give me ideas or advices.
I'm trying to implement this class named Map
. it should contain 2 iterators - iterator
and const_iterator
.
I have them implemented - iterator
inherits from const_iterator
, and in the Map
class I have the following functions:
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
we were given an example file to see what is required to implement. in there, there is the following code:
Map<std::string,int> msi;
...
// print map
for(Map<std::string,int>::const_iterator it = msi.begin(); it != msi.end(); ++it) {
// more stuff here
}
since msi
is a non-const Map instance, msi.begin()
calls to iterator begin()
and not const_iterator begin() const
, resulting in unintended behaviour.
Assuming the example file is okay, how do I make it so msi.begin()
calls the correct const_iterator
function? (considering it, the iterator, is of type const_iterator
).
EDIT: regarding the talk about the auto-conversion, i decided to add my iterator classes, please point out my mistake.
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 standard containers add cbegin
and cend
for that purpose. Lacking that, you can obviously always cast your object to const&
explicitly to get a const
view on the object.
More fundamentally, however, there’s no reason why your iterator
shouldn’t support an automatic conversion to const_iterator
. Like that, you’d not need to change the client code at all. In fact, your code should already support this if, as you’ve said, iterator
inherits from const_iterator
.
However, the code you’ve posted contains several errors. Firstly, operator=
is wrong, and you should have received an error for it. The corrected version is:
void operator=(const_iterator target) {
currNode = target.currNode;
}
More importantly, your inheritance makes no sense. True, you do inherit iterator
from const_iterator
but your code pretends that this never happened – iterator
completely reimplements its parent class and doesn’t relate to it in any way.
iterator
should rather look something like this:
class iterator : public const_iterator {
public:
iterator(Node* cur_node = NULL) : const_iterator(cur_node) {}
};
This requires of course that currNode
is declared protected
in const_iterator
. That class is also completely useless (but so is yours, at the moment) since it doesn’t add any functionality to the const_iterator
class. You need to implement an operator*
which allows modifying its value. Your current code fundamentally doesn’t allow this since it returns a newly created string rather than (something akin to) a reference to a map value.
Furthermore, it’s unclear how the const_iterator
class gets ahold of a non-const
Node
pointer in the first place. That shouldn’t be possible: after all, it gets the pointer from a const Map
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With