这是我编写的一个双向链接列表类:
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;
}
};
在DLL
的好友函数中,将DLL
输出到流中,出现了一个错误,提示该函数无法访问类Node
的私有成员。
经过几次尝试,我通过将此好友函数声明为Node
类的好友,提出了一个解决方案,如下所示:
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);
};
现在函数std::ostream& operator<<(std::ostream& out, const DLL& dll)
可以访问m_next
类中的Node
,并且一切正常,或者我认为是。
我的问题是:一个函数可以像我们在这里看到的那样成为一个以上类的朋友吗,或者我所做的事情会调用未定义的行为吗?
是的,一个函数可以是一个以上类的朋友。
但是朋友不是继承的,因此即使operator<<
是DLL<T>
的朋友,并且DLL<T>
是DLL<T>::Node
的朋友,它也不会自动使operator<<
成为DLL<T>::Node
的朋友,因此无法访问private DLL<T>::Node::m_next
。
解决方案是像您一样将它声明为DLL<T>::Node
的朋友。
仅在某些类中的朋友函数声明指定该函数作为该类的朋友,而不是成员。您绝对可以成为多个类的函数朋友。例如:
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;
}