c++operator-overloadingc++98

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


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.

#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.


Solution

  • 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:

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