friend declaration

From cppreference.com
 
 
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Initialization
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
Classes
friend specifier
initializer lists
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

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.

Contents

[edit] Syntax

friend function-declaration (1)
friend function-definition (2)
friend type-specifier ; (3)
friend elaborated-class-name ; (4)

[edit] Description

1) Designates a function or several functions as friends of this class
class Y {
    int data; // private member
    // the non-member function operator<< will have access to Y's private members
    friend std::ostream& operator<<(std::ostream& out, const Y& o);
    friend char* X::foo(int); // members of other classes can be friends too
    friend X::X(char), X::~X(); // constructors and destructors can be friends
};
// friend declaration does not declare a member function
// this operator<< still needs to be defined, as a non-member
std::ostream& operator<<(std::ostream& out, const Y& y)
{
    return out << y.data; // can access private member Y::data
}
2) (only allowed in non-local class definitions) Defines a non-member function, and makes it a friend of this class at the same time. Such non-member function is always inline.
class X {
    int a;
    friend void friend_set(X& p, int a) {
        p.a = i; // this is a non-member function
    }
 public:
    void member_set(int a) {
        a = i; // this is a member function
    }
};
3) Designates the class, struct, or union named by the type-specifier as a friend of of this class. This means that the friend's member declarations and definitions can access private and protected members of this class and also that the friend can inherit from private and protected members of this class.
4) If the name of the class that is used in the friend declaration is not yet declared, it can be forward declared on the spot by using elaborated type name (the keyword class, struct, or union followed by class name).
class Y {};
class A {
    int data; // private data member
    class B { }; // private nested type
    enum { a = 100 }; // private enumerator
    friend Y; // friend class declaration
    friend class X; // friend class forward declaration
};
 
class X : A::B { // OK: A::B accessible to friend
    A::B mx; // OK: A::B accessible to member of friend
    class Y {
        A::B my; // OK: A::B accessible to nested member of friend
    };
    int v[A::a]; // OK: A::a accessible to member of friend
};

[edit] 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)

Storage class specifiers are not allowed in friend function declarations. A function that is defined in the friend declaration has external linkage, a function that was previously defined, keeps the linkage it was defined with.

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:

class F {};
int f();
int main()
{
    extern int g();
    class Local { // Local class in the main() function
        friend int f(); // Error, no such function declared in main()
        friend int g(); // OK, there is a declaration for g in main()
        friend class F; // friends a local F (defined later)
        friend class ::F; // friends the global F
    };
    class F {}; // local F
}

[edit] Example

stream insertion and extraction operators are often declared as non-member friends

#include <iostream>
#include <sstream>
 
class MyClass {
    int i;
 
    friend std::ostream& operator<<(std::ostream& out, const MyClass& o);
    friend std::istream& operator>>(std::istream& in, MyClass& o);
 public:
    MyClass(int i = 0) : i(i) {}
};
 
std::ostream& operator<<(std::ostream& out, const MyClass& mc)
{
    return out << mc.i;
}
 
std::istream& operator>>(std::istream& in, MyClass& mc)
{
    return in >> mc.i;
}
 
int main()
{
    MyClass mc(7);
    std::cout << mc << '\n';
    std::istringstream("100") >> mc;
    std::cout << mc << '\n';
}

Output:

7
100

[edit] See Also

Class declaration
Access specifiers