修复 C++遗留代码:类迭代器

发布于 2024-12-12 21:34:00 字数 2384 浏览 2 评论 0原文

作为数据结构类作业的一部分,我试图让这个已有十多年历史的代码实际工作。代码可以在这里找到: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 实现的迭代器,而是使用 Stack 的父类 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 时(),看看 Container 中的方法调用就会发现:

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

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

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

有什么想法吗?

As part of an assignment for a data structures class, I am trying to get this over a decade-old code to actually work. The code is found here: http://www.brpreiss.com/books/opus4/

(And to all of the users here who are horrified at such bad design, take heart - this is a homework assignment where the goal is ostensibly to get someone else's code to work. I am not advocating its use.)

Here, the author defined the class Stack and its associated 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

I am not sure what the objective is here, because trying to instantiate a StackAsLinkedList::Iter will predictably give an error because it is private. Furthermore, the author doesn't use the iterator he just implemented for stack in the below example, which instead uses the iterator defined in the parent class of Stack called Container to traverse the stack and print the values:

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;
}

...

But when he creates stack.NewIterator(), a look at the method call in Container shows:

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

So the conditional in the while statement will always fail and thus the body will never execute.

This leads me to believe that I should be implementing another NewIterator method for Stack, but I am not sure what the return value should be ( *new StackAsLinkedList::Iter(_stack) ?).

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

九歌凝 2024-12-19 21:34:00

在 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)。但正如我上面所说,目标是让这些东西在有限的时间内编译并运行。因此,为了回应其他人所说的:请不要使用此代码!

Adding the following method in StackAsLinkedList seemed to clear up the problem:

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

Also, the order of assignment in main() was also an issue. This seemed to correct it:

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;
}

I realize that this solution is not ideal - ideally I should refactor or better yet just start over (or just use STL). But as I said above, the goal was to just get this stuff to compile and work within a limited time-frame. So to echo what others have said: please don't use this code!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文