C++:使函数成为多个 类 的朋友?
C++: Making a function friend of multiple classes?
这是我写的双向链表class:
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
输出到流中,弹出一个错误说函数无法访问class的私有成员Node
.
经过几次尝试,我想出了一个解决方案,将这个友元函数声明为 Node
class 的友元函数,如下所示:
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)
可以访问 Node
class 中的 m_next
并且一切正常......我认为是这样。
我的问题是:一个函数能否成为多个函数的友元 class 正如我们在这里看到的,或者我所做的是否会调用未定义的行为?
是的,一个函数可以是多个函数的友元class。
但是朋友不会被继承,所以即使 operator<<
是 DLL<T>
的朋友并且 DLL<T>
是 DLL<T>::Node
的朋友,它不会自动使 operator<<
DLL<T>::Node
的朋友,因此无法访问 private DLL<T>::Node::m_next
。
解决方案是像您一样将其声明为 DLL<T>::Node
的好友。
某些 class 中的友元函数声明仅 指定 函数作为 class 的友元,而不是成员。你绝对可以让多个 classes 成为函数的朋友。例如:
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;
}
这是我写的双向链表class:
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
输出到流中,弹出一个错误说函数无法访问class的私有成员Node
.
经过几次尝试,我想出了一个解决方案,将这个友元函数声明为 Node
class 的友元函数,如下所示:
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)
可以访问 Node
class 中的 m_next
并且一切正常......我认为是这样。
我的问题是:一个函数能否成为多个函数的友元 class 正如我们在这里看到的,或者我所做的是否会调用未定义的行为?
是的,一个函数可以是多个函数的友元class。
但是朋友不会被继承,所以即使 operator<<
是 DLL<T>
的朋友并且 DLL<T>
是 DLL<T>::Node
的朋友,它不会自动使 operator<<
DLL<T>::Node
的朋友,因此无法访问 private DLL<T>::Node::m_next
。
解决方案是像您一样将其声明为 DLL<T>::Node
的好友。
某些 class 中的友元函数声明仅 指定 函数作为 class 的友元,而不是成员。你绝对可以让多个 classes 成为函数的朋友。例如:
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;
}