How to overload << operator in nested class - c++

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.

Another approach.
Keep Database::Node:print() very simple -- print the data on the object only.
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;
}

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

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

Related

Is ostream& operator<< better practice in a class than using std::cout?

In a Linked List class, I created a display method to print out the Linked List as it is currently formulated like so:
void LinkedList::display() {
Node* curr = m_head;
while (curr) {
std::cout << curr->n_data << " -> ";
curr = curr->n_next;
}
std::cout << std::endl;
}
One of the TA's who graded the assignment left a comment:
Never do cout in a class file. Use ostream& operator<< instead.
Classes shouldn't care about where you are outputting to (file/console/etc).
We hadn't yet learned about operator overloading at the time of this assignment, but I'm still not really sure.
How would I actually implement and use the ostream& operator>> to print to the console? Why is this best practice?
The simplest solution in this case would be to add a std::ostream parameter to your display() method, eg:
void LinkedList::display(std::ostream &out) const {
Node* curr = m_head;
while (curr) {
out << curr->n_data << " -> ";
curr = curr->n_next;
}
out << std::endl;
}
LinkedList list;
...
list.display(std::cout);
Then, if down the line, you decide to overload operator<<, it can simply call display(), eg:
std::ostream& operator<<(std::ostream &out, const LinkedList &list) {
list.display(out);
return out;
}
LinkedList list;
...
std::cout << list;

How to access the child class through the parent class object with shared pointers

I have a linked list using a parent Node class and a child Node class (called Transaction). The linked list class (called Ledger) is using shared pointers to access the Node and Transaction class.
My goal is to use the << operator with a shared pointer of Node, called endPtr (the linked list uses a tail instead of a head, going from last to first), and traverse each Node instance and access the Transaction class variables of that parent Node and print them out.
This is my Node header file:
#pragma once
#include <memory>
#include <string>
#include <vector>
using namespace std;
class Node {
protected:
shared_ptr<Node> prev;
string nodeType;
public:
Node();
Node(shared_ptr<Node>);
shared_ptr<Node> getPrev() const;
void setPrev(shared_ptr<Node>);
string getType();
};
My Transaction header file that inherits from Node:
#pragma once
#include "Node.h"
class Transaction: public Node {
private:
string toName;
string fromName;
int amount;
public:
Transaction();
Transaction(string, string, int);
string getToName() const;
string getFromName() const;
int getAmount() const;
void setToName(string);
void setFromName(string);
void setAmount(int);
shared_ptr<Transaction> getPrev();
void setPrev(shared_ptr<Transaction>);
};
And this is the Ledger header and cpp files:
class Ledger {
private:
string toName;
string fromName;
int amount;
vector<pair<string, int>> ledgerVector;
shared_ptr<Node> endPtr;
int count = 0;
public:
Ledger();
Ledger& operator+=(Transaction);
Ledger& operator-=(shared_ptr<Transaction>);
void Add(Transaction);
friend ostream& operator<<(ostream& os, const Ledger&);
};
cpp:
Ledger& Ledger::operator+=(Transaction newTxn) {
shared_ptr<Transaction> newTransaction = make_shared<Transaction>(newTxn);
shared_ptr<Node> newPointer = make_shared<Node>(newTxn);
if (endPtr != nullptr) {
newPointer->setPrev(endPtr);
endPtr = newPointer;
}
else
endPtr = newPointer;
}
ostream& operator<<(ostream& os, const Ledger& ledger) {
weak_ptr<Node> newNode = ledger.endPtr;
auto node = newNode.lock();
while (node != nullptr) {
if (node->getType() == "TRANSACTION") {
shared_ptr<Transaction> transNode = make_shared<Transaction>(node.get());
string fromName = transNode->getFromName();
cout << fromName << endl;
}
node = node->getPrev();
}
}
Finally, main.cpp:
Transaction t1 = Transaction("Albert", "Bob", 100);
Transaction t2 = Transaction("James", "Alice", 50);
Ledger myLedger;
myLedger += t1;
myLedger += t2;
cout << myLedger;
As you can see in the += operator, that is how I'm adding new transaction nodes, by converting the Transaction into a smart pointer and then creating a Node smart pointer from the same Transaction. At which point, I've assigned it the endPtr of the Ledger class.
This is what the endPtr looks like, as seen through Node instances:
The endPtr has two Node instances, as attempted in the main(), but I have no idea if the content of the Transaction is stored in them as well, nor do I know how to access it.
I understand there is no reason to go about it this way, as it may not be optimal, but any guidance on accessing inherited class variables through a parent object instance while using smart pointers would be greatly appreciated.
Your Ledger's operator+= (and presumably Add()) and operator<< are implemented incorrectly. Try this instead:
class Ledger {
...
public:
...
Ledger& operator+=(const Transaction&);
...
void Add(const Transaction&);
friend ostream& operator<<(ostream& os, const Ledger&);
};
void Ledger::Add(const Transaction &newTxn)
{
auto newPointer = make_shared<Transaction>(newTxn);
newPointer->setPrev(endPtr);
endPtr = newPointer;
}
Ledger& Ledger::operator+=(const Transaction &newTxn) {
Add(newTxn);
return *this;
}
ostream& operator<<(ostream& os, const Ledger& ledger) {
auto node = ledger.endPtr;
while (node != nullptr) {
auto transNode = dynamic_pointer_cast<Transaction>(node);
if (transNode != nullptr) {
os << transNode->getFromName() << endl;
}
node = node->getPrev();
}
return os;
}

Invalid use of template name ' ' without an argument list

I'm trying to create simple stack using linked lists in C++. Suddenly I encountered the problem which is (I think) connected with templates. I lack knowledge in that structures thats why I tried to create something and learn with it.
My problem is with node * top; what should I change ? any idea?
My code is :
#include <iostream>
#include <cstdlib>
using namespace std;
template<typename T>
class node {
public:
T object;
node * next;
};
node *top = NULL;
template<typename T>
class Stack{
public:
void push(T obj);
void pop();
void display(ostream & out) const;
};
void Stack :: push(T obj){
node * tempNode = new node;
tempNode->object = obj;
tempNode->next = top;
top = tempNode;
}
void Stack :: display(ostream & out) const{
if(top == NULL){
cout << "Stack is Empty"<<endl;
return;
}
else{
node *temp = top;
while(temp!=NULL){
cout << "Here is your elements :"<<"\n";
cout << temp->object<<endl;
temp = temp->next;
}
cout <<endl;
}
}
void Stack :: pop(){
if (top = NULL){
cout << "List is Empty"<<endl;
return;
}
cout << "Your object: "<<top->object << " is removed"<<endl;
top = top->next;
}
ostream & operator << (ostream & out, const Stack & s){
s.display(out);
return out;
}
I'm guessing top should be a member of Stack not a global variable? You also need to specify the template type of node:
template<typename T>
class Stack{
node<T> *top = NULL;
public:
void push(T obj);
void pop();
void display(ostream & out) const;
};
When defining methods of templated classes out of line you need to specify the template type for the class:
template<typename T>
void Stack<T> :: push(T obj){
Your << operator also needs to be a template:
template<typename T>
ostream & operator << (ostream & out, const Stack<T> & s){
s.display(out);
return out;
}

Print Function - Linked-List c++

I am trying to figure out what I am doing wrong with this printList Function. I am getting the following compiler error:
No operator "<<" matches these operands.
The function is as follows:
void printList(const List& theList)
{
for(Node* i = theList.getFirst(); i != theList.getLast(); ++i)
{
cout << *i << " ";
cout << endl;
}
}
I have the following as well,
#include "List.h"
#include <iostream>
I am thinking my print function is just way off base. Can anyone point me in the right direction?
Here are my classes, I don't have a List::Iterator. What would you suggest?
class List
{
private:
int nodeListTotal;
Node* first;
Node* last;
public:
//Constructor
List();
void push_back(Node*);
void push_front(Node*);
Node* pop_back();
Node* pop_front();
Node* getFirst() const;
Node* getLast() const;
int getListLength() const;
void retrieve(int index, int& dataItem) const;
};
class Node
{
private:
string dataItem;
string dataUnit;
int unitTotal;
Node* next;
public:
//Constructor
Node();
Node(int, string, string);
string getDescription( );
void setDescription(string);
string getQuantityName();
void setQuantityName(string);
int getQuantityNumber();
void setQuantityNumber(int);
Node* getNext( );
void setNext(Node*);
};
You need to overload operator<< for Node type:
std::ostream& operator<<(std:::ostream& os, const Node& node)
{
os << node.getQuantityName() << " " << node.getDescription();
return os;
}
As the error message says
No operator "<<" matches these operands.
you don't have the << operator defined for your class.
In your printList() function, replace cout << *i << " "; with
cout << i->getDescription() << endl;

Linked List output crash

My program hangs when outputting contents of my linked list. I can't change the header, only the cpp file.
playlist.h:
class PlayList {
private:
struct SongNode {
Song data;
SongNode* next;
SongNode (const Song& s, SongNode* nxt = 0)
: data(s), next(nxt)
{}
};
friend std::ostream& operator<< (std::ostream& out, const PlayList& s);
SongNode* first; // head of a list of songs, ordered by title, then artist
//Snip...
inline
std::ostream& operator<< (std::ostream& out, const PlayList& pl)
{
for (PlayList::SongNode* current = pl.first; current != 0; current = current->next)
out << current->data << std::endl;
return out;
}
playlist.cpp
using namespace std;
PlayList::PlayList()
: totalTime(0,0,0)
{
}
void PlayList::operator+= (const Song& song)
{
SongNode* newNode = new SongNode(song, first);
first = newNode;
}
When outputting the list all of the data that is supposed to print, does print, but then the program hangs.
In the constructor of class PlayList, you need to initialise first:
public:
PlayList() : first(NULL) {}
Otherwise, in your operator<<, you reach the end of the list and instead of encountering NULL, you just get a junk pointer.
You forgot to initialize first in the constructor.