关于 c++98 中 linkedlist 类中重载非成员运算符<<的问题

Question on overload non-member operator << in a linkedlist class in c++98

提问人:Jac Investigator 提问时间:4/19/2023 最后编辑:Jac Investigator 更新时间:4/19/2023 访问量:56

问:

谁能帮我解决这个问题?对于背景信息,我有三个类,带有 、 、 和 包含 。除了打印出链接列表之外,所有当前功能都在工作,这是我问题的基础。Account.hAccount.cppNode.hNode.cppLinkedList.hLinkedlist.cppdemo.cppint main()

问题具体说:

实现一个非成员重载函数,该函数使用 from ,以允许您执行如下操作:operator <<operator <<Account

cout << MyLinkedList << endl;

我从 和 复制了与此问题相关的代码的特定部分,因为如果我将其全部粘贴到此处,它会太长。LinkedList.cppAccount.cpp

带有重载函数“尚未工作”的代码如下所示: 请注意 是 的 typedef。LinkedList.cppoperator <<value_typeAccount

#include "LinkedList.h"
    
LinkedList::value_type LinkedList::getCurrent() const {
    if (current != NULL) {
        return current->getData();
    } else {
        return value_type();
    }
}
    
ostream& operator << (ostream& out, const LinkedList& list) { // not working, compile error!
    value_type current = getCurrent();
    while (current != NULL) {
        out << "(" << acc.getName() << "," << acc.balance() << ")" << endl;
    }
    return out;
}

代码如下图所示:Account.cpp

ostream& operator << (ostream& out, const Account& acc)
{
    out << "(" << acc.getName() << "," << acc.balance() << ")" << endl;
    return out;
}

这些是我的node.h文件的类声明:

#ifndef TEKAAI_NODE
#define TEKAAI_NODE

#include "Account.h"

class Node
{
    public:
        // members that are externally visible 
        
        // Below are Member functions
        
        // specifying value_type to Account using typedef
        typedef Account value_type;
        
        // Default constructor
        
        Node();     
        
        // Parameter Constructors
        
        Node(const value_type& initial_data, Node* initial_link);
        
        ~Node();    //destructor
        
        void setNext(Node* n);
        
        void setPrevious(Node* p);
        
        Node* getNext() const;
        
        Node* getPrevious() const;
        
        // the data getters and setters
        // Pre-condition: Current has been initialized 
        // Post-condition: set data
        void setData(const value_type& i);
        
        // Pre-condition: Data has been initialized
        // Post-condition: returns stored data
        value_type getData() const;
        
    private:
        value_type data;    //the data held by the node
        Node* next;         //a pointer to the next node
        Node* previous;     //a pointer to the previous node
};
#endif

这些是我的 LinkedList.h 文件中的类声明:

#ifndef TEKAAI_LINKEDLIST_H
#define TEKAAI_LINKEDLIST_H

#include "Account.h"
#include "Node.h"
#include <iostream>

class LinkedList
{
    public:
        typedef Account value_type;
        // Members that are externally visible
        
        // These are Member functions
        
        // Constructors
            
        LinkedList();   
        
        // Destructor
        
        ~LinkedList();
        
        void addToHead(const value_type& account); 
        
        void addToTail(const value_type& account);
        
        void addCurrent(const value_type& account);
        
        value_type removeFromHead();
        
        value_type removeFromTail();
        
        value_type removeFromCurrent();
        
        // Pre-condition: LinkedList contains nodes
        // Post-condition: moves current to the head 
        void start();  

        // Pre-condition: LinkedList contains nodes
        // Post-condition: moves current to the tail
        void end();
        
        // Pre-condition: LinkedList contains nodes
        // Post-condition: moves current one node to the right
        void forward();  
        
        // Pre-condition: LinkedList contains nodes
        // Post-condition: moves current one node to the left
        void back(); 
        
        // Pre-condition: LinkedList contains nodes
        // Post-condition: returns the value of data account stored 
        // in current node
        value_type getCurrent() const;
        
        // Pre-condition: LinkedList is initialized, containing 
        // nodes
        // Post-condition: returns the length of the list
        int length();
    
    private:
        Node* head;
        Node* tail;
        Node* current;
};  
ostream& operator << (ostream& out, const LinkedList& list);

#endif  

正如你在上面的LinkedList类声明中看到的,我必须与它们合作,尝试打印出我的linkedlist。我想听听您的想法,是否可以使用上述函数之一打印我的链接列表,同时还可以使用帐户中的重载<<运算符作为指定的问题。

谢谢。

另外注意:只是为了让您知道我可以使用函数“Node* getHead() const;”打印我的 linkedlist;,该函数在重载 << 运算符时返回 head,但我只是在寻求帮助是否可以在不使用 getHead() 函数的情况下打印 linkedlist。我猜我们的讲师只是在惹我们,试图让我们对他的实验室活动失去理智。

C++ 运算符重载 C++98

评论

1赞 HolyBlackCat 4/19/2023
我们不需要你的整个代码,但我们需要一个最小的可重现示例。请阅读链接并制作一个。
1赞 user12002570 4/19/2023
“请注意value_type是帐户的 typedef......”如果您只发布 MRE 会更好。
1赞 Alan Birtles 4/19/2023
还请显示编译器输出的全文,错误是什么?如果没有最小的可重现示例或编译器错误,我们几乎没有机会帮助您。猜测是不可复制的,但你通过值将其传递给运算符,请确保使用引用LinkedList
0赞 Jac Investigator 4/19/2023
@HolyBlackCat,我已经编辑并发布了 LinkedList 类的所有类声明。您认为可以使用上述函数之一以及使用 Account 类中的重载 >> 运算符打印出我的链表吗?

答:

2赞 Remy Lebeau 4/19/2023 #1

首先,你的 应该通过 const 引用而不是通过值来获取它们的第二个参数,例如:operator<<

ostream& operator << (ostream& out, const Account& acc)
ostream& operator << (ostream& out, const LinkedList& list)

其次,是的,可以在运算符内部使用运算符。您需要与以下内容等效的内容(因为您没有提供完整的类声明):AccountLinkedList

ostream& operator << (ostream& out, const LinkedList& list) {
    LinkedList::Node *cur = list.getFirst();
    while (cur != NULL) {
        out << cur->getData();
        cur = cur->getNext();
    }
    return out;
}

更新:现在你已经发布了你的类声明,我看到它没有提供任何类似方法的东西。它有 和 用于迭代列表的方法,但没有方法可以指示迭代何时到达列表末尾。LinkedListgetFirst()start()forward()

因此,您有以下几种选择:

  • 添加一个新方法以指示可以安全调用:getCurrent()
class LinkedList
{
    public:
        ...        
        bool hasCurrent() const;
        value_type getCurrent() const;        
        ...    
};  
bool LinkedList::hasCurrent() const {
    return (current != NULL);
}

LinkedList::value_type LinkedList::getCurrent() const {
    return current->getData();
}
ostream& operator << (ostream& out, LinkedList& list) {
    list.start();
    while (list.hasCurrent()) {
        out << list.getCurrent();
        list.forward();
    }
    return out;
}
  • 更改方法以按指针而不是按值返回对象,以便当迭代位于列表末尾时,它可以返回指getCurrent()AccountNULL
class Node
{
    public:
        ...        
        value_type& getData();
        ...
};
LinkedList::value_type* LinkedList::getCurrent() {
    if (current != NULL) {
        return &(current->getData());
    } else {
        return NULL;
    }
}
ostream& operator << (ostream& out, LinkedList& list) {
    Account *cur;
    list.start();
    while ((cur = list.getCurrent()) != NULL) {
        out << *cur;
        list.forward();
    }
    return out;
}
  • 使运算符成为类的 A,以便它可以直接访问私有成员:LinkedListfriendLinkedListhead
class LinkedList
{
    public:
        ...
        friend ostream& operator << (ostream& out, const LinkedList& list);
        ...

    private:
        Node* head;
        ... 
};  

ostream& operator << (ostream& out, const LinkedList& list);
ostream& operator << (ostream& out, const LinkedList& list) {
    Node *cur = list.head;
    while (cur != NULL) {
        out << cur->getData();
        cur = cur->getNext();
    }
    return out;
}

评论

0赞 Jac Investigator 4/19/2023
嗨,@Remy Lebeau,感谢您的回答,供您参考,我已经编辑了我的帖子以包含我对 LinkedList 的类声明。您认为可以使用类中的函数之一以及使用 Account 类中的<<重载运算符打印出我的链表吗?
1赞 Remy Lebeau 4/19/2023
@TekaaiKaewaniti给定 LinkedList 类中的现有方法,则不。我已经用替代解决方案更新了我的答案。