C ++:使函数成为多个类的朋友?

问题描述 投票:0回答:2

这是我编写的一个双向链接列表类:

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,并且一切正常,或者我认为是。

我的问题是:一个函数可以像我们在这里看到的那样成为一个以上类的朋友吗,或者我所做的事情会调用未定义的行为吗?

c++ oop friend friend-function
2个回答
0
投票

是的,一个函数可以是一个以上类的朋友。

但是朋友不是继承的,因此即使operator<<DLL<T>的朋友,并且DLL<T>DLL<T>::Node的朋友,它也不会自动使operator<<成为DLL<T>::Node的朋友,因此无法访问private DLL<T>::Node::m_next

解决方案是像您一样将它声明为DLL<T>::Node的朋友。


0
投票

仅在某些类中的朋友函数声明指定该函数作为该类的朋友,而不是成员。您绝对可以成为多个类的函数朋友。例如:

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

© www.soinside.com 2019 - 2024. All rights reserved.