修复C ++遗留代码:类Iterator

时间:2011-10-30 19:22:17

标签: c++ iterator stack legacy-code

作为数据结构类的赋值的一部分,我试图让这个十多年的代码实际工作。代码可在此处找到:http://www.brpreiss.com/books/opus4/

(对于那些对这种糟糕设计感到恐惧的所有用户而言,请放心 - 这是一项家庭作业,其目标明显是为了让其他人的代码能够运作。我并不主张使用它。

在这里,作者定义了类Stack及其相关的Iterator:

#ifndef STACK_H
#define STACK_H

#include "linkList.h"
#include "container.h"

class Stack : public virtual Container
{
public:

    virtual Object& Top () const = 0;
    virtual void Push (Object&) = 0;
    virtual Object& Pop () = 0;
};

class StackAsLinkedList : public Stack
{
    LinkedList<Object*> list;
    class Iter;

public:

    StackAsLinkedList () : list() {}
    ~StackAsLinkedList() { Purge(); }

    //
    // Push, Pop and Top
    //
    void Push(Object& object);
    Object& Pop() override;
    Object& Top() const override;

    int CompareTo(Object const& obj) const;

    //
    // purge elements from, and accept elements onto, the list
    //
    void Purge();
     void Accept (Visitor&) const;

     friend class Iter;
 };

class StackAsLinkedList::Iter : public Iterator
{
    StackAsLinkedList const& stack;
    ListElement<Object*> const* position;

public:

    Iter (StackAsLinkedList const& _stack) : stack(_stack) { Reset(); }

    //
    // determine whether iterator is pointing at null
    //
    bool IsDone() const { return position == 0; }

    //
    // overloaded dereference and increment operator
    //
    Object& operator*() const;
    void   operator++();

    void Reset() { position = stack.list.Head(); }
};

#endif

我不确定这里的目标是什么,因为尝试实例化StackAsLinkedList :: Iter会出现错误,因为它是私有的。此外,作者没有使用他刚刚在下面的例子中为堆栈实现的迭代器,而是使用在父类Stack中调用的迭代器来遍历堆栈并打印值:

StackAsLinkedList stack;
Iter& i = stack.NewIterator();

stack.Push(*new Int(1) );     //type "Int" is a Wrapper for primitive "int"
stack.Push(*new Int(2) );
...

while ( ! outIter.IsDone() )
{
    cout << *outIter << endl;
    ++outIter;
}

...

但是当他创建stack.NewIterator()时,看看Container中的方法调用显示:

virtual Iterator& NewIterator () const { return *new NullIterator (); }

因此,while语句中的条件总是会失败,因此正文将永远不会执行。

这让我相信我应该为Stack实现另一个NewIterator方法,但我不确定返回值应该是什么(* new StackAsLinkedList :: Iter(_stack)?)。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

在StackAsLinkedList中添加以下方法似乎可以解决问题:

Iterator& StackAsLinkedList::NewIterator() const
{ 
    return *new Iter(*this); 
}

此外,main()中的赋值顺序也是一个问题。这似乎纠正了它:

StackAsLinkedList stack;

stack.Push(*new Int(1) );     //type "Int" is a Wrapper for primitive "int"
stack.Push(*new Int(2) );
...

Iter& i = stack.NewIterator();

while ( ! outIter.IsDone() )
{
    cout << *outIter << endl;
    ++outIter;
}

我意识到这个解决方案并不理想 - 理想情况下我应该重构或更好但只是重新开始(或者只是使用STL)。但正如我上面所说,目标是让这些东西在有限的时间范围内编译和工作。所以回应其他人所说的话:请不要使用此代码!