【问题标题】:in c++ my operator overloading prefix not work在 C++ 中,我的运算符重载前缀不起作用
【发布时间】:2020-12-05 19:35:37
【问题描述】:

问题已修改

我有一个包含 add()begin() 函数的列表类(如链接列表) add() 添加到尾部的函数 begin()函数返回第一个元素(head)的地址

我试图让我的班级支持范围for(:) 所以我尝试实现begin()end()operator++() 函数,但我被困在operator++() 它不起作用 (阅读下面的注释)

新增功能

问题是i 是一个节点指针,所以我不能这样做++i,它只会增加指针的地址,它不会运行operator++(),因为它不是一个节点指针一个来自 Node 结构的对象,所以当我这样做时 ++(*i) 它将运行 operator++()

#include <iostream>
using namespace std;
class List
{
    struct Node
    {
        int info;
        Node *next;
        Node(int val) : info(val), next(NULL) {}
        
       Node * operator++(){ // not working
            cout << "i am alive\n";
            *this = *this->next;
            return this;
        }
    };
    Node *head = NULL;
    Node *tail = NULL;

public:
    void add(int val) // add to tail, O(1)
    {
        Node *temp = new Node(val);

        if (!head)
        {
            head = temp;
            tail = temp;
            return;
        }

        tail->next = temp;
        tail = temp;
    }
    Node *begin()
    {
        return head;
    }
};
int main()
{
    List l;
    l.add(2);
    l.add(5);
    l.add(10);
        
    auto i = l.begin(); // *i is 2
    ++i; 
    cout << (*i).info; // output is 0
}

请注意: 如果我这样做,它将工作并打印 5

    auto i = l.begin(); // *i is 2
    i->operator++(); // will work
    // ++(*i); //also will work
    cout << (*i).info; // output is 5

【问题讨论】:

  • 尝试用实际类型替换auto。它在这里没有帮助
  • operator++Node 类的成员函数。 i 是一个 Node* 指针。您正在更改函数调用 - ++i 的等效项是 i.operator++(),但您调用的是 i-&gt;operator++()。但除此之外,Node 类中的operator++ 不会更改它被调用的Node,它会返回一个Node* 指针,而不是Node
  • 您可能想要创建一个迭代器类并在迭代器上使用 operator++。
  • @largest_prime_is_463035818,解决问题(删除 auto 并将其替换为 Node* ,但这解决了问题我将 Node 类移到 List 类之外.
  • 不,它没有解决问题,它只是让它更显眼

标签: c++ oop operator-overloading


【解决方案1】:

您对增量运算符的实现方法是错误的。它不应该返回增加的值。相反,它应该增加它被调用的对象的值。然后,它应该为前缀变体返回对该对象的引用或在后缀变体中返回前值的副本。

您的代码的问题还在于它将苹果与橙子进行比较。您的 i 是一个指针,++i 只会增加该指针。它不关心您的类是否实现了增量运算符。为了调用它,你需要++*i

【讨论】:

  • 当我这样做时你的我是对的++(*i); 它可以工作,我如何改进代码以使用++i 你能写代码来理解它吗
  • 看看C++标准库代码就知道了。 Boost 中还有一个库来方便迭代器编码。提示:您的迭代器仅包含一个指针,并在元素之间移动该指针。
  • 看起来我不想使用库或任何我试图在课堂上处理范围的外部东西,我应该创建一个 begin()end()operator++() 函数跨度>
  • 是的,还有什么比来自 C++ 标准库或 Boost 的现有高级代码更好的学习方法?
  • 我明白你的意思,我可以学习并理解实现,并在我的课堂上做,我会尝试的
【解决方案2】:

谢谢大家,我按照你说的自己实现了迭代器类解决了这个问题

我的课程现在支持范围 for(:)

#include <iostream>
using namespace std;

class List
{
    struct Node
    {
        int info;
        Node * next;
        Node(int val): info(val), next(NULL) {}
    };

    class Iterator
    {
        Node * ptr;
    public:
        Iterator(Node *p): ptr(p) {}

        Iterator & operator=(Node * Np)
        {
            ptr = Np;
            return *this;
        }

        bool operator!=(Iterator & it)
        {
            return this->ptr != it.ptr;
        }

        Iterator &operator++()
        {
            if (ptr)
            {
                ptr = ptr->next;
                return * this;
            }
        }

        Iterator &operator++(int)
        {
            Iterator it = *this;
            ++(*this);
            return it;
        }

        int operator*()
        {
            return ptr->info;
        }
    };

    Node *head = NULL;
    Node *tail = NULL;

public:
    void add(int val)   // add to tail, O(1)
    {
        Node *temp = new Node(val);

        if (!head)
        {
            head = temp;
            tail = temp;
            return;
        }

        tail->next = temp;
        tail = temp;
    }

    Iterator begin()
    {
        return Iterator(head);
    }

    Iterator end()
    {
        return Iterator(NULL);
    }
};
int main()
{
    List l;
    l.add(2);
    l.add(5);
    l.add(10);

    auto i = l.begin();
    ++i;
    cout << *i <<'\n'; // output 5
    
    for(auto it : l){
        cout << it <<' '; // output 2 5 10
    }
}

【讨论】:

    【解决方案3】:

    您可以使用Node 轻松实现如下所示的const 类似迭代器的对象。但是,如果您希望能够通过迭代器修改列表,则可能必须创建一个新类。

    Node &operator++(){
        return *this = *this->next;
    }
    
    int operator*() {
      return this->info;
    }
    
    Node cbegin() {
      return *head;
    }
    

    【讨论】:

    • 这仍然有一个问题,写一个可能是constoperator++ 是非常意外的。
    • 不确定,但我认为 OP 想写 ++i;i 产生影响。随着您的更改 OPs main 仍然是错误的
    • 您建议的运算符中没有const
    • 但最终这一切只是突出了Node 和迭代器不是真正 相同的问题,因为现在调用operator++ 来尝试移动列表周围实际上会重新排列列表的内容。我们需要一个实际的迭代器类,其行为类似于 Node* 指针,但具有正确的递增和递减行为。
    • Iterator 是公认的设计模式。请不要用这个名字来称呼任何“类似于”迭代器的东西,这可能会误导新手,因为它在软件工程中是一个相当严格的概念。并不是说我反对你的提议:)
    猜你喜欢
    • 2014-05-16
    • 2012-01-05
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    相关资源
    最近更新 更多