我阅读了与此问题相关的一些其他线程,但没有为我的问题提供解决方案。希望大家能给我一些想法或者建议。

我正在尝试实现这个名为 Map. 。它应该包含 2 个迭代器 - iteratorconst_iterator.

我已经实施了它们 - iterator 继承自 const_iterator, ,并且在 Map I类有以下功能:

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标准容器添加 cbegincend 为了这个目的。缺乏这一点,你显然总是可以将你的对象投射到 const& 明确地得到一个 const 对物体的看法。

然而,更根本的是,你没有理由 iterator 不应该支持自动转换为 const_iterator. 。这样,您根本不需要更改客户端代码。事实上,如果正如您所说,您的代码应该已经支持这一点: iterator 继承自 const_iterator.

但是,您发布的代码包含多个错误。首先, operator= 是错误的,您应该收到一个错误。更正后的版本是:

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

更重要的是,你的继承毫无意义。确实,你 继承 iteratorconst_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 指针放在第一位。这不应该是不可能的:毕竟,它从 a 获取指针 const Map.

其他提示

如果你定义msi

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

代替

Map<std::string,int> msi;

将调用 begin() 和 end() 的 const 版本

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top