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

Demo