Friend declaration

The friend declaration appears in a class body and grants a function or another class access to private and protected members of the class where the friend declaration appears.

# Notes

Friendship is not transitive (a friend of your friend is not your friend).

Friendship is not inherited (your friend’s children are not your friends, and your friends are not your children’s friends).

Access specifiers have no effect on the meaning of friend declarations (they can appear in private: or in public: sections, with no difference).

A friend class declaration cannot define a new class (friend class X {}; is an error).

When a local class declares an unqualified function or class as a friend, only functions and classes in the innermost non-class scope are looked up, not the global functions:

A name first declared in a friend declaration within a class or class template X becomes a member of the innermost enclosing namespace of X, but is not visible for lookup (except argument-dependent lookup that considers X) unless a matching declaration at namespace scope is provided - see namespaces for details.

# Example

#include <iostream>
#include <sstream>
 
class MyClass
{
    int i;                   // friends have access to non-public, non-static
    static inline int id{6}; // and static (possibly inline) members
 
    friend std::ostream& operator<<(std::ostream& out, const MyClass&);
    friend std::istream& operator>>(std::istream& in, MyClass&);
    friend void change_id(int);
public:
    MyClass(int i = 0) : i(i) {}
};
 
std::ostream& operator<<(std::ostream& out, const MyClass& mc)
{
    return out << "MyClass::id = " << MyClass::id << "; i = " << mc.i;
}
 
std::istream& operator>>(std::istream& in, MyClass& mc)
{
    return in >> mc.i;
}
 
void change_id(int id) { MyClass::id = id; }
 
int main()
{
    MyClass mc(7);
    std::cout << mc << '\n';
//  mc.i = 333*2;  // error: i is a private member
    std::istringstream("100") >> mc;
    std::cout << mc << '\n';
//  MyClass::id = 222*3;  // error: id is a private member
    change_id(9);
    std::cout << mc << '\n';
}

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
CWG 45C++98members of a class nested in a friendclass of T have no special access to Ta nested class has the sameaccess as the enclosing class
CWG 500C++98friend class of T cannot inherit from private orprotected members of T, but its nested class canboth can inheritfrom such members
CWG 1439C++98the rule targeting friend declarations in non-localclasses did not cover template declarationscovered
CWG 1477C++98a name first declared in a friend declaration within a classor class template was not visible for lookup if the matchingdeclaration is provided in another namespace scopeit is visible forlookup in this case
CWG 1804C++98when a member of a class template is friended, the correspondingmember of specializations of partial specializations of the classtemplate was not a friend of the class granting friendshipsuch membersare also friends
CWG 2379C++11friend declarations referring to full specializationsof function templates could be declared constexprprohibited
CWG 2588C++98the linkages of names introduced by friend declarations were unclearmade clear

# See also