英文:
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`。所有当前的函数都能正常工作,只有打印出链表的功能还没实现,这也是我的问题所在。
问题明确要求:
> 实现一个非成员重载的 `operator <<` 函数,使用 `Account` 中的 `operator <<`,允许你执行如下操作:
> `cout << MyLinkedList << endl;`
我从 `LinkedList.cpp` 和 `Account.cpp` 中复制了与这个问题相关的特定部分,因为如果我把所有代码都粘贴在这里,会太长了。
在 `LinkedList.cpp` 中,有一个未能正常工作的重载的 `operator <<` 函数,代码如下所示:请注意 `value_type` 是 `Account` 的 typedef。
```c++
#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:
// 外部可见的成员
// 以下是成员函数
// 使用 typedef 将 value_type 指定为 Account
typedef Account value_type;
// 默认构造函数
Node();
// 参数构造函数
Node(const value_type& 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& 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 "Account.h"
#include "Node.h"
#include <iostream>
class LinkedList
{
public:
typedef Account value_type;
// 外部可见的成员
// 这些是成员函数
// 构造函数
LinkedList();
// 析构函数
~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();
// 前提条件:链表包含节点
// 后置条件:将当前节点移到头部
void start();
// 前提条件:链表包含节点
// 后置条件:将当前节点移到尾部
void end();
// 前提条件:链表包含节点
// 后置条件:将当前节点向右移动一个节点
void forward();
// 前提条件:链表包含节点
// 后置条件:将当前节点向左移动一个节点
void back();
// 前提条件:链表包含节点
// 后置条件:返回当前节点存储的数据帐户的值
value_type getCurrent() const;
// 前提条件:链表已初始化,包含节点
// 后置条件:返回链表的长度
int length();
private:
Node* head;
Node* tail;
Node* current;
};
ostream& operator << (ostream& out, const LinkedList& 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:
> Implement a non-member overloaded `operator <<` function, that uses the `operator <<` from `Account`, to allow you to perform an operation like:
>
> `cout << MyLinkedList << 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 <<` function "not yet working" is as shown below: Please note `value_type` is typedef for `Account`.
```c++
#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;
}
Code from Account.cpp
is as shown below:
ostream& operator << (ostream& out, const Account& acc)
{
out << "(" << acc.getName() << "," << acc.balance() << ")" << endl;
return out;
}
These are the class declarations for my node.h file:
#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
These are the class declarations in my LinkedList.h file:
#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
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 theAccount
object by pointer instead of by value so that it can return aNULL
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 afriend
of theLinkedList
class so it can access the privatehead
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<<
'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 theAccount
object by pointer instead of by value so that it can return aNULL
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 afriend
of theLinkedList
class so it can access the privatehead
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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论