Исправление унаследованного кода C ++: класс Iterator - PullRequest
0 голосов
/ 30 октября 2011

Как часть задания для класса структур данных, я пытаюсь заставить его работать с более чем десятилетним кодом.Код можно найти здесь: http://www.brpreiss.com/books/opus4/

(И всем пользователям здесь, которые в ужасе от такого плохого дизайна, наберитесь духа - это домашнее задание, цель которого якобы состоит в том, чтобы получить чужой код дляработа. Я не защищаю его использование. )

Здесь автор определил класс Stack и связанный с ним итератор:

#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, как и ожидалось, приведет к ошибке, поскольку она является закрытой.Кроме того, автор не использует итератор, который он только что реализовал для стека в приведенном ниже примере, который вместо этого использует итератор, определенный в родительском классе стека с именем Container, для обхода стека и печати значений:

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 (), проверка вызова метода в контейнере показывает:

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

Таким образом, условное выражение в операторе while всегда будет терпеть неудачу и, следовательно, тело никогда не будет выполнено.

Это наводит меня на мысль, что я должен реализовать другой метод NewIterator для стека, но я не уверен, каким должно быть возвращаемое значение (* new StackAsLinkedList :: Iter (_stack)?).

Есть идеи?

1 Ответ

1 голос
/ 31 октября 2011

Добавление следующего метода в 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). Но, как я сказал выше, цель состояла в том, чтобы просто скомпилировать этот материал и работать в течение ограниченного периода времени. Итак, чтобы повторить то, что сказали другие: пожалуйста, не используйте этот код!

...