Reputation: 432
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?
Upvotes: 1
Views: 401
Reputation: 13269
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;
}
Upvotes: 1
Reputation: 85471
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.
Upvotes: 1