Overloading ostream << operator for a class with private key member - c++

I am trying to overload the ostream << operator for class List
class Node
{
public:
int data;
Node *next;
};
class List
{
private:
Node *head;
public:
List() : head(NULL) {}
void insert(int d, int index){ ... }
...}
To my humble knowledge (overload ostream functions) must be written outside the class. So, I have done this:
ostream &operator<<(ostream &out, List L)
{
Node *currNode = L.head;
while (currNode != NULL)
{
out << currNode->data << " ";
currNode = currNode->next;
}
return out;
}
But of course, this doesn't work because the member Node head is private.
What are the methods that can be done in this case other than turning Node *head to public?

You can solve this by adding a friend declaration for the overloaded operator<< inside class' definition as shown below:
class List
{
//add friend declaration
friend std::ostream& operator<<(std::ostream &out, List L);
//other member here
};

Declare the function signature inside the class and mark it as friend, then define it outside the class if you want.

Related

Private member c++ problems [duplicate]

This question already has answers here:
C++ operator overloading and accessing private data variables
(2 answers)
Closed 1 year ago.
I've run into an error that I don't know how to fix. My program does not compile because it outputs "declared private here". Not sure how to fix this, looking for feedback in order to improve my skills! Thanks in advance.
I've only included the areas where I am experiencing issues.
class List
{
public:
List() { first = NULL; } // constructor
List(const List& source); // copy constructor
~List(); // destructor
int length() const; // returns the length of the list that invokes it
bool present(const int& target) const;
void insert(const int& entry); // inserts the item n into the invoking list, in the appropriate position
void merge(List, List); // merges the two lists l1 and l2 into the invoking list
void makeEmpty(); // re-initializes an exisiting list to be empty
friend ostream& operator<<(ostream& out, List& c); // friend function for class
private:
struct Node
{
int data;
Node *next;
};
Node *first;
Node* get_node(const int& entry, Node* link); // allocates, initializes, and returns the address of a new node
};
ostream& operator << (ostream& out, const List& c)
{
List::Node *cursor;
out << " ";
for (cursor = c.first; cursor != NULL && cursor -> next != NULL; cursor = cursor -> next)
out << cursor -> data << ", ";
if (cursor != NULL)
out << cursor -> data;
out << " ";
return out;
}
Here is what my compiler outputs
301Project3test.cpp: In function 'std::ostream& operator<<(std::ostream&, const List&)':
301Project3test.cpp:166:11: error: 'struct List::Node' is private within this context
List::Node *cursor;
301Project3test.cpp:30:16: note: declared private here
struct Node
301Project3test.cpp:170:21: error: 'List::Node* List::first' is private within this context
for (cursor = c.first; cursor != NULL && cursor -> next != NULL; cursor = cursor -> next)
301Project3test.cpp:35:15: note: declared private here
Node *first;
List declares its friend operator<< as taking a List&, but you are implementing the operator as taking a const List& instead, so you are actually implementing a different operator, not the friend operator that has access to the private List::Node type.

C++: Making a function friend of multiple classes?

Here's a Doubly Linked List class that I wrote:
template <class T>
class DLL
{
class Node
{
T m_data;
Node* m_prev;
Node* m_next;
Node(const T& data) :m_data{ data }, m_prev{ nullptr }, m_next{ nullptr }{}
friend class DLL;
friend std::ostream& operator<<(std::ostream& out, const Node& node)
{
out << node.m_data;
return out;
}
};
Node* m_first = nullptr;
public:
DLL& add(const T& data)
{
Node* temp = new Node{ data };
if (m_first)
{
temp->m_next = m_first;
m_first->m_prev = temp;
m_first = temp;
}
else {
m_first = temp;
}
return *this;
}
friend std::ostream& operator<<(std::ostream& out, const DLL& dll)
{
Node* trav = dll.m_first;
while (trav)
{
out << *trav << ' ';
trav = trav->m_next; //C2248: Cannot access private member declared in class DLL::Node.
}
return out;
}
~DLL()
{
Node* trav = m_first->m_next;
Node* foll = m_first;
while (trav)
{
delete foll;
foll = trav;
trav = trav->m_next;
}
delete foll;
}
};
In the DLL's friend function to output the DLL into stream, there's an error that pops up saying the function cannot access a private member of the class Node.
After a couple of tries, I came up with a solution by declaring this friend function as a friend of the Node class as seen below:
class Node
{
T m_data;
Node* m_prev;
Node* m_next;
Node(const T& data) :m_data{ data }, m_prev{ nullptr }, m_next{ nullptr }{}
friend class DLL;
friend std::ostream& operator<<(std::ostream& out, const Node& node)
{
out << node.m_data;
return out;
}
friend std::ostream& operator<<(std::ostream& out, const DLL& dll);
};
Now the function std::ostream& operator<<(std::ostream& out, const DLL& dll) is able to access m_next in the Node class and everything's working fine...or so I think.
My question here is: Can a function be a friend of more than one class as we see here or does what I've done invoke undefined behavior?
Yes, a function can be a friend of more than one class.
But friends are not inherited, so even if operator<< is a friend of DLL<T> and DLL<T> a friend of DLL<T>::Node, it doesn't automatically make operator<< a friend of DLL<T>::Node, hence it can't access the private DLL<T>::Node::m_next.
The solution is to declare it a friend of DLL<T>::Node, like you did.
A friend function declaration in some class only designates the function as a friend of that class, not as a member. You can absolutely make a function friend of multiple classes. For example:
class B;
class A {
int a = 2;
friend auto operator+(A a, B b) -> int;
};
class B {
int b = 5;
friend auto operator+(A a, B b) -> int;
};
auto operator+(A a, B b) -> int {
return a.a + b.b;
}
Demo

friend function can't access private struct

I'm trying to write a friend function to go through a linked list and output the characters in the list, but for some reason I can't declare Nodes within the friend function. Here is my code:
This is the function:
std::ostream& operator<<(std::ostream& out, LinkedList& list)
{
Node *tempNode = nullptr;
*tempNode = *beginningOfList;
std::cout << "list: ";
while(tempNode)
{
std::cout << tempNode->letter;
if (tempNode->next)
std::cout << ", ";
tempNode = tempNode->next;
}
return out;
}
Here is the header file:
#ifndef _LINKED_LIST_
#define _LINKED_LIST_
#include <ostream>
class LinkedList
{
public:
LinkedList();
~LinkedList();
void add(char ch);
bool find(char ch);
bool del(char ch);
friend std::ostream& operator<<(std::ostream& out, LinkedList& list);
private:
struct Node
{
char letter;
Node *next;
};
Node *beginningOfList;
};
#endif // _LINKED_LIST_
When I try to compile it, I get the messages "Node was not declared in this scope," as well as "*tempNode was not declared in this scope" and "*beginningOfList was not declared in this scope." I'm guessing the problem has to do with namespaces, but I'm really not sure.
It's telling the truth. Node etc were not declared in that scope. Your operator is a global function but those things are in the scope of LinkedList. Try calling them LinkedList::Node, list->beginningOfList etc.

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

operator<< overload in C++ for a class in class

i have the following classes:
class mypipe {
class node {
public:
char ch;
node* next;
node(){...}
node(char c){..}
} ;
public:
unsigned int size;
node* head;
and i need to overload the operator<<, to print the mypipe as it is now.
then, i'm trying to write the following:
friend ostream& operator<< (ostream& stream, mypipe p) {
node* curr = p.head -> next;
...
immediately after the variables definition.
the problem is that i get an error "identifier node is undefined".
i've tried to declare the operator and implement it outside of the class, that didn't help.
does anyone have any ideas about it?
thanks in advance for anyone who can help :)
node is an inner class, which means you have to qualify its type:
mypipe::node* curr = p.head -> next;