Исправление устаревшего кода C : итератор класса

#c #iterator #stack #legacy-code

#c #итератор #стек #устаревший код

Вопрос:

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

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

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

 #ifndef STACK_H
#define STACK_H

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

class Stack : public virtual Container
{
public:

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

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

public:

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

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

    int CompareTo(Object constamp; obj) const;

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

     friend class Iter;
 };

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

public:

    Iter (StackAsLinkedList constamp; _stack) : stack(_stack) { Reset(); }

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

    //
    // overloaded dereference and increment operator
    //
    Objectamp; operator*() const;
    void   operator  ();

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

#endif
 

Я не уверен, какова здесь цель, потому что попытка создать экземпляр StackAsLinkedList::Iter предсказуемо выдаст ошибку, поскольку она является частной. Кроме того, автор не использует итератор, который он только что реализовал для стека в приведенном ниже примере, который вместо этого использует итератор, определенный в родительском классе стека с именем Container, для обхода стека и печати значений:

 StackAsLinkedList stack;
Iteramp; 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;
}

...
 

Но когда он создает стек.NewIterator(), взгляд на вызов метода в контейнере показывает:

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

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

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

Есть идеи?

Комментарии:

1. итак, ваша домашняя работа исправляет эту древнюю книгу?

2. Это действительно плохая идея return *new something , потому что вы забудете об delete этом.

3. -1, чтобы отговорить других от использования этого кода. Непонятно, зачем вам нужен итератор для стека — по сравнению со списком, разве не в том, что вы ничего не можете сделать, кроме как нажимать и выскакивать?

4. @phooji: это довольно несправедливо — давать мне -1. Возможно, я был недостаточно ясен, когда пометил это как домашнее задание, но это действительно домашнее задание, которое требует от меня исправить «древний код» этого парня. Не думайте, что я выступаю за его использование. Я просто прошу помощи, чтобы заставить это задание работать в соответствии с инструкциями для этого задания.

5. @phooji: Кроме того, я понимаю, что инженеры-программисты, работающие в промышленности, должны поддерживать устаревший код, каким бы плохо он ни был написан. Так что это может быть полезно для тех, кто имеет дело с теми же проблемами поддержки плохо разработанного кода (но кода, который, тем не менее, работает).

Ответ №1:

Добавление следующего метода в StackAsLinkedList, похоже, решило проблему:

 Iteratoramp; 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) );
...

Iteramp; i = stack.NewIterator();

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

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