Medvednic
Medvednic

Reputation: 692

How to overload << operator in nested class

I have three classes: Client Database and Node as a nested class in Database.

Data of a Node is a pointer to a Client object, the Client class has it's own overloaded << operator.

I need to have an overloaded << operator that will output all of the linked list's data. The problem that I encounter is not being able to iterate through all of the list using the << overloaded operator, the best thing that I can do is to output the head node's data using getData member, for some reason Node::Print won't output all of the lists Client *data.

Here is the Database class and two of the mentioned methods << and print().

Databse.h

class Databse
{
    private:
        class Node //node as nested class
        {
            public:
                Node();
                void setNode(Client*&);
                Node* nextNode(Node*&);
                Client getData();
                void print (Node*);
            private:
                Client* data; //holds pointer to Client object
                Node* next; //holds pointer to next node in list
        };

        Node *head; //holds the head node
        int nClients;

    public:
        Databse();
        friend ostream& operator<<(ostream&, const Databse&);
        Node* getHead() const;
        ~Databsey();
};

Databse.cpp relevant methods:

ostream& operator<<(ostream& out, const Databse& obj)
{   
    out << endl << "The databse holds" << obj.nClients << " clients:" << endl;
    out << obj.head->getData();        
    obj.head->print(obj.getHead());
    return out;
}

void Database::Node::print (Node* str)
{
    Node* current = str ;
    while (current->next)
    {
        cout << current->data;
        current = current->next;
    }
}

Thanks.

Upvotes: 0

Views: 1970

Answers (3)

R Sahu
R Sahu

Reputation: 206567

Another approach.

  1. Keep Database::Node:print() very simple -- print the data on the object only.
  2. Let ostream& operator<<(ostream& out, const Database& obj) take care of iterating over the nodes in the list and print each node.

Here's the updated code.

class Database
{
   private:
      class Node //node as nested class
      {
         public:
            Node();
            void setNode(Client*&);
            Node* nextNode(Node*&);

            // Need this to allow iteration of the list of nodes
            // of a Database object.
            Node* nextNode() const
            {
               return next;
            }
            Client getData();

            // Print the data associated with just one node.
            void print(ostream& out) const
            {
               cout << data;
            }

         private:
            Client* data; //holds pointer to Client object
            Node* next; //holds pointer to next node in list
      };

      Node *head; //holds the head node
      int nClients;

   public:
      Database();
      friend ostream& operator<<(ostream&, const Database&);
      Node* getHead() const;
      ~Database();
};

ostream& operator<<(ostream& out, const Database& obj)
{   
    out << endl << "The databse holds" << obj.nClients << " clients:" << endl;

    // Iterate over the nodes of the Database object
    // and print each one.
    Database::Node* current = obj.head;
    for ( ; current != NULL; current = current->nextNode() )
    {
       current->print(out);
       // Printing a whitespace between nodes makes the
       // output more readable.
       out << " ";
    }

    return out;
}

Upvotes: 2

Thomas Russell
Thomas Russell

Reputation: 5970

Just add the overloaded operator<< as you would with any other class, for instance:

class Databse
{
    private:
        class Node //node as nested class
        {
            public:
                Node();
                void setNode(Client*&);
                Node* nextNode(Node*&);
                Client getData();
                friend ostream& operator<<( ostream&, const Node*& pNode );
            private:
                Client* data; //holds pointer to Client object
                Node* next; //holds pointer to next node in list
        };

        Node *head; //holds the head node
        int nClients;

    public:
        Databse();
        friend ostream& operator<<(ostream&, const Databse&);
        friend ostream& operator<<( ostream&, const Node*& pNode );
        Node* getHead() const;
        ~Databsey();
};

And then implement it as follows:

ostream& operator<<( ostream& out, const std::add_lvalue_reference<Databse::Node*>::type pNode )
{
    Databse::Node* pCurrNode = pNode;
    while( pCurrNode )
    {
        std::cout << pCurrNode->data;
        pCurrNode = pCurrNode->next;
    }

    return out;
}

Upvotes: 2

Luka Rahne
Luka Rahne

Reputation: 10447

fix print that accept ostream

ostream& Database::Node::print (ostream& out, Node* str)
{
  Node* current = str ;
  while (current) //bugfix
  {
    out << current->data;
    current = current->next;
  }
  return out
}

and then you can call

ostream& operator<<(ostream& out, const Databse& obj)
{   
  out << endl << "The databse holds" << obj.nClients << " clients:" << endl;
  out << obj.head->getData();        
  obj.head->print(out,obj.getHead());
  return out;
}

Upvotes: 1

Related Questions