在C++98中,关于链表类的非成员重载运算符<<的问题。

huangapple go评论50阅读模式
英文:

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

问题

Sure, here's the translated code you provided:

有人可以帮我解答这个问题吗?为了提供背景信息,我有三个类,`Account.h`  `Account.cpp`,`Node.h`  `Node.cpp`,`LinkedList.h`  `Linkedlist.cpp`,以及包含 `int main()`  `demo.cpp`。所有当前的函数都能正常工作,只有打印出链表的功能还没实现,这也是我的问题所在。

问题明确要求:

&gt; 实现一个非成员重载的 `operator &lt;&lt;` 函数,使用 `Account` 中的 `operator &lt;&lt;`,允许你执行如下操作:

&gt; `cout &lt;&lt; MyLinkedList &lt;&lt; endl;`

我从 `LinkedList.cpp`  `Account.cpp` 中复制了与这个问题相关的特定部分,因为如果我把所有代码都粘贴在这里,会太长了。

 `LinkedList.cpp` 中,有一个未能正常工作的重载的 `operator &lt;&lt;` 函数,代码如下所示:请注意 `value_type`  `Account`  typedef

```c++
#include &quot;LinkedList.h&quot;
    
LinkedList::value_type LinkedList::getCurrent() const {
    if (current != NULL) {
    	return current-&gt;getData();
    } else {
    	return value_type();
    }
}
    
ostream&amp; operator &lt;&lt; (ostream&amp; out, const LinkedList&amp; list) { // not working, compile error!
    value_type current = getCurrent();
    while (current != NULL) {
        out &lt;&lt; &quot;(&quot; &lt;&lt; acc.getName() &lt;&lt; &quot;,&quot; &lt;&lt; acc.balance() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    }
    return out;
}

Account.cpp 中的代码如下:

ostream&amp; operator &lt;&lt; (ostream&amp; out, const Account&amp; acc)
{
    out &lt;&lt; &quot;(&quot; &lt;&lt; acc.getName() &lt;&lt; &quot;,&quot; &lt;&lt; acc.balance() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    return out;
}

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

#ifndef TEKAAI_NODE
#define TEKAAI_NODE

#include &quot;Account.h&quot;

class Node
{
	public:
		// 外部可见的成员
		
		// 以下是成员函数
		
		// 使用 typedef 将 value_type 指定为 Account
		typedef Account value_type;
		
		// 默认构造函数
		
		Node();		
		
		// 参数构造函数
		
		Node(const value_type&amp; initial_data, Node* initial_link);
		
		~Node();	// 析构函数
		
		void setNext(Node* n);
		
		void setPrevious(Node* p);
		
		Node* getNext() const;
		
		Node* getPrevious() const;
		
		// 数据的获取和设置
		// 前提条件:Current 已初始化
		// 后置条件:设置数据
		void setData(const value_type&amp; i);
		
		// 前提条件:数据已初始化
		// 后置条件:返回存储的数据
		value_type getData() const;
		
	private:
		value_type data;	// 节点保存的数据
		Node* next; 		// 指向下一个节点的指针
		Node* previous;		// 指向前一个节点的指针
};
#endif

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

#ifndef TEKAAI_LINKEDLIST_H
#define TEKAAI_LINKEDLIST_H

#include &quot;Account.h&quot;
#include &quot;Node.h&quot;
#include &lt;iostream&gt;

class LinkedList
{
    public:
		typedef Account value_type;
		// 外部可见的成员
		
		// 这些是成员函数
		
		// 构造函数
		    
		LinkedList();	
		
		// 析构函数
		
		~LinkedList();
		
		void addToHead(const value_type&amp; account); 
		
		void addToTail(const value_type&amp; account);
		
		void addCurrent(const value_type&amp; account);
		
		value_type removeFromHead();
		
		value_type removeFromTail();
		
        value_type removeFromCurrent();
		
	    // 前提条件:链表包含节点
		// 后置条件:将当前节点移到头部 
	    void start();  

	    // 前提条件:链表包含节点
	    // 后置条件:将当前节点移到尾部
	    void end();
		
	    // 前提条件:链表包含节点
	    // 后置条件:将当前节点向右移动一个节点
	    void forward();  
		
	    // 前提条件:链表包含节点
	    // 后置条件:将当前节点向左移动一个节点
	    void back(); 
		
	    // 前提条件:链表包含节点
	    // 后置条件:返回当前节点存储的数据帐户的值
	    value_type getCurrent() const;
		
	    // 前提条件:链表已初始化,包含节点
	    // 后置条件:返回链表的长度
	    int length();
	
	private:
	    Node* head;
	    Node* tail;
	    Node* current;
};	
ostream&amp; operator &lt;&lt; (ostream&amp; out, const LinkedList&amp; list);

#endif	

正如你在上面的 LinkedList 类声明中看到的,我必须使用其中一个上面的函数之一来尝试打印我的链表。我想听听你的意见,是否可能使用上述 Account 中的重载 << 操作符以及其中一个函数来打印我的链表,正如问题所指定的那样。

谢谢。

另外请注意:只是想让你知道,我可以使用函数 Node* getHead() const; 打印我的链表,该函数返回头部,但我只是想知道是否可以在不使用 getHead() 函数的情况下打印链表。我想我们的讲师只是在玩弄我们,试图通过他的实验活动让我们失去理智。


<details>
<summary>英文:</summary>
Can anyone help me with this question please? For background information, I have three classes, `Account.h` with `Account.cpp`, `Node.h` with `Node.cpp`, `LinkedList.h` with `Linkedlist.cpp`, and `demo.cpp` that contains `int main()`. All of the current functions are working except for printing out the linkedlist, which is the basis of my question.
The question specifically says:
&gt; Implement a non-member overloaded `operator &lt;&lt;` function, that uses the `operator &lt;&lt;` from `Account`, to allow you to perform an operation like:
&gt;
&gt; `cout &lt;&lt; MyLinkedList &lt;&lt; endl;`
I copied specific parts of my code related to this question from `LinkedList.cpp` and `Account.cpp` because it will be too long if I paste it all here.
Code from `LinkedList.cpp` with overloaded `operator &lt;&lt;` function &quot;not yet working&quot; is as shown below: Please note `value_type` is typedef for `Account`.
```c++
#include &quot;LinkedList.h&quot;
LinkedList::value_type LinkedList::getCurrent() const {
if (current != NULL) {
return current-&gt;getData();
} else {
return value_type();
}
}
ostream&amp; operator &lt;&lt; (ostream&amp; out, const LinkedList&amp; list) { // not working, compile error!
value_type current = getCurrent();
while (current != NULL) {
out &lt;&lt; &quot;(&quot; &lt;&lt; acc.getName() &lt;&lt; &quot;,&quot; &lt;&lt; acc.balance() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
}
return out;
}

Code from Account.cpp is as shown below:

ostream&amp; operator &lt;&lt; (ostream&amp; out, const Account&amp; acc)
{
    out &lt;&lt; &quot;(&quot; &lt;&lt; acc.getName() &lt;&lt; &quot;,&quot; &lt;&lt; acc.balance() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    return out;
}

These are the class declarations for my node.h file:

#ifndef TEKAAI_NODE
#define TEKAAI_NODE

#include &quot;Account.h&quot;

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&amp; 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&amp; 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

These are the class declarations in my LinkedList.h file:

#ifndef TEKAAI_LINKEDLIST_H
#define TEKAAI_LINKEDLIST_H

#include &quot;Account.h&quot;
#include &quot;Node.h&quot;
#include &lt;iostream&gt;

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&amp; account); 
		
		void addToTail(const value_type&amp; account);
		
		void addCurrent(const value_type&amp; 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&amp; operator &lt;&lt; (ostream&amp; out, const LinkedList&amp; list);

#endif	

As you can see in LinkedList class declarations above,I have to work with them to try and print out my linkedlist. I would like to hear your thoughts if it is possible to print my linkedlist using one of the above functions while also using the overloaded << operator from Account as the question specified.

Thanks.

PLUS NOTE: Just to let you know that I can get to print my linkedlist using the function 'Node* getHead() const;' which returns head in overloading the << operator, but I was just looking for help if it is possible to print linkedlist without using the getHead() function. I guess our lecturer was just messing with us, trying to make us lose our minds with his lab activity.

答案1

得分: 2

First, your operator<<'s should be taking their 2nd parameters by const reference, not by value, eg:

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

Second, yes, it is possible to use the Account operator inside the LinkedList operator. You need something equivalent to the following (since you didn't provide full class declarations):

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

UPDATE: now that you have posted your LinkedList class declaration, I see that it does not offer anything like a getFirst() method. It has start() and forward() methods for iterating the list, but there is no method to indicate when the iteration has reached the end of the list.

So, you have a few options:

  • add a new method to indicate that getCurrent() is safe to call:
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;
}
  • change your getCurrent() method to return the Account object by pointer instead of by value so that it can return a NULL pointer when the iteration is at the end of the list:
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;
}
  • make the LinkedList operator be a friend of the LinkedList class so it can access the private head member directly:
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;
}
英文:

First, your operator&lt;&lt;'s should be taking their 2nd parameters by const reference, not by value, eg:

ostream&amp; operator &lt;&lt; (ostream&amp; out, const Account&amp; acc)
ostream&amp; operator &lt;&lt; (ostream&amp; out, const LinkedList&amp; list)

Second, yes, it is possible to use the Account operator inside the LinkedList operator. You need something equivalent to the following (since you didn't provide full class declarations):

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

UPDATE: now that you have posted your LinkedList class declaration, I see that it does not offer anything like a getFirst() method. It has start() and forward() methods for iterating the list, but there is no method to indicate when the iteration has reached the end of the list.

So, you have a few options:

  • add a new method to indicate that getCurrent() is safe to call:
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-&gt;getData();
}
ostream&amp; operator &lt;&lt; (ostream&amp; out, LinkedList&amp; list) {
list.start();
while (list.hasCurrent()) {
out &lt;&lt; list.getCurrent();
list.forward();
}
return out;
}
  • change your getCurrent() method to return the Account object by pointer instead of by value so that it can return a NULL pointer when the iteration is at the end of the list:
class Node
{
    public:
        ...        
        value_type&amp; getData();
        ...
};
LinkedList::value_type* LinkedList::getCurrent() {
    if (current != NULL) {
        return &amp;(current-&gt;getData());
    } else {
        return NULL;
    }
}
ostream&amp; operator &lt;&lt; (ostream&amp; out, LinkedList&amp; list) {
    Account *cur;
    list.start();
    while ((cur = list.getCurrent()) != NULL) {
        out &lt;&lt; *cur;
        list.forward();
    }
    return out;
}
  • make the LinkedList operator be a friend of the LinkedList class so it can access the private head member directly:
class LinkedList
{
    public:
        ...
        friend ostream&amp; operator &lt;&lt; (ostream&amp; out, const LinkedList&amp; list);
        ...

    private:
        Node* head;
        ... 
};  

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

huangapple
  • 本文由 发表于 2023年4月19日 15:04:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76051604.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定