Por que o << Operador é amigo

#include <iostream>

class Paragraph
{
    public:
        explicit Paragraph(std::string const& init)
            :m_para(init)
        {}

        std::string const&  to_str() const
        {
            return m_para;
        }

        bool operator==(Paragraph const& rhs) const
        {
            return m_para == rhs.m_para;
        }
        bool operator!=(Paragraph const& rhs) const
        {
            // Define != operator in terms of the == operator
            return !(this->operator==(rhs));
        }
        bool operator<(Paragraph const& rhs) const
        {
            return  m_para < rhs.m_para;
        }
    private:
        friend std::ostream & operator<<(std::ostream &os, const Paragraph& p);
        std::string     m_para;
};

std::ostream & operator<<(std::ostream &os, const Paragraph& p)
{
    return os << p.to_str();
}


int main()
{
    Paragraph   p("Plop");
    Paragraph   q(p);

    std::cout << p << std::endl << (p == q) << std::endl;
}
Lucky Leopard