Language[lang]

C++ friend class and friend function: syntax and rules

Section
Language [lang]
Standard
C++17
Compilers
MSVC 19.44, Clang 19.1 (MSVC STL), GCC 16.2, Clang 23.1 (libc++)
Published
Length
7 min read
In this answer7 clauses
  1. 1How do you declare a friend class in C++?
  2. 2What is a friend function?
  3. 3How do you print a class with operator<<?
  4. 4Is friendship mutual, inherited or transitive?
  5. 5When should you use friend?
  6. 6Does friend break encapsulation?
  7. 7Friend class or friend function: a checklist

Abstract

A C++ friend class is a class that another class lets use its private and protected members: the owner writes friend class Auditor; inside its own body, and a single function, such as the operator<< that prints the class, can be made a friend the same way. Friendship goes one way: it is not mutual, not inherited by derived classes and not transitive. Use a member function when you can and a friend when you have to.

A frame holds two hatched cells and a small copy of the blue block outside, whose solid arrow enters a hatched cell. A plain block farther off sends a crossed-out dashed arrow that ends at the frame.
Figure 1 — Access is granted by the owner, one friend at a time.

A C++ friend class is a class that another class allows to use its private and protected members. The class granting access writes friend class Auditor; inside its own body, and a single function can be made a friend the same way. Friendship is one-way: not mutual, not inherited by derived classes, not passed on to a friend’s friends.

Here Account keeps its balance private and lets Auditor add two balances up:

[Example 1:
#include <iostream>

class Account {
public:
    explicit Account(double start) : balance(start) {}

private:
    double balance;

    friend class Auditor;  // Auditor may use the private members
};

class Auditor {
public:
    double total(const Account& a, const Account& b) const {
        return a.balance + b.balance;  // allowed: Auditor is a friend
    }
};

int main() {
    Account savings(1200.0);
    Account checking(350.5);
    Auditor auditor;
    std::cout << "Total: " << auditor.total(savings, checking) << '\n';
}

— end example]

It printed Total: 1550.5.

The samples are C++17, built with MSVC 19.44, Clang 19.1 (MSVC STL), GCC 16.2 and Clang 23.1 (libc++), and all four agreed on every one. friend has been in the language since C++98, so nothing here needs a newer standard; Since When lists what each standard added.

How do you declare a friend class in C++?

Put friend class Auditor; inside the class whose private members Auditor may use, as Account does above. Only the owner can grant access: no class can declare itself a friend of another from outside. A private member, usable only by the class’s own code (see how a C++ class is defined), is then open to every member function of Auditor too.

The line can go anywhere in the class body. Under private: or public: it means the same, since access labels have no effect on friend declarations, and Auditor need not be declared before it: all four compilers built both.

Without the friend line, the same access does not compile. Account never named Stranger:

[Example 2:
class Stranger {
public:
    double peek(const Account& a) const {
        return a.balance;  // error: Stranger is not a friend
    }
};

— end example]

Clang says 'balance' is a private member of 'Account'; MSVC reports the same mistake as error C2248.

What is a friend function?

A friend function is an ordinary function, not a member of the class, that the class lets use its private members. Declare it inside the class with friend, then define it outside like any other function, with no Account:: in front. It has no this, so it gets the accounts it compares as parameters:

[Example 3:
class Account {
public:
    explicit Account(double start) : balance(start) {}

    friend bool richer(const Account& a, const Account& b);

private:
    double balance;
};

// A plain function: no Account:: in front, no this inside.
bool richer(const Account& a, const Account& b) {
    return a.balance > b.balance;  // allowed: richer is a friend
}

int main() {
    Account savings(1200.0);
    Account checking(350.5);
    std::cout << std::boolalpha;
    std::cout << richer(savings, checking) << '\n';  // true
    std::cout << richer(checking, savings) << '\n';  // false
}

— end example]

It printed true, then false.

One member function of another class can be a friend too, once that class is defined:

[Example 4:
class Account;  // declared, so Auditor can name it

class Auditor {  // defined before Account names its member
public:
    double total(const Account& a, const Account& b) const;
};

class Account {
public:
    explicit Account(double start) : balance(start) {}

private:
    double balance;

    // Only this one member function of Auditor is a friend.
    friend double Auditor::total(const Account& a,
                                 const Account& b) const;
};

double Auditor::total(const Account& a, const Account& b) const {
    return a.balance + b.balance;
}

— end example]

With Auditor only declared, all four compilers rejected the friend line.

How do you print a class with operator<<?

Make operator<< a friend function and define it right inside the class. The stream sits on the left of std::cout << acct, so the operator cannot be a member of Account; as a friend it can still read balance:

[Example 5:
class Account {
public:
    explicit Account(double start) : balance(start) {}

    friend std::ostream& operator<<(std::ostream& os,
                                    const Account& a) {
        return os << "Account with balance " << a.balance;
    }

private:
    double balance;
};

int main() {
    Account acct(1200.5);
    std::cout << acct << '\n';
}

— end example]

All four printed Account with balance 1200.5. Defined inside the class, the function is still not a member; the compiler finds it through its argument’s class, so it needs no declaration outside. Operator overloading in C++ covers >> and the rest.

Is friendship mutual, inherited or transitive?

No, on all three counts. The standard says “Friendship is neither inherited nor transitive” ([class.friend]), and it is not mutual either: each access is granted by the class that owns the data.

Not mutual: Account names Auditor a friend, so Auditor may read balance, but Account gets nothing back. Auditor’s private notes stay closed to it:

[Example 6:
class Account {
public:
    explicit Account(double start) : balance(start) {}

    std::string read_notes(const Auditor& au) const {
        return au.notes;  // error: Account is not Auditor's friend
    }

private:
    double balance;

    friend class Auditor;  // Auditor may read Account, not back
};

double Auditor::balance_of(const Account& a) const {
    return a.balance;  // allowed: Auditor is Account's friend
}

— end example]

Not inherited: SeniorAuditor, a derived class of Auditor, does not inherit its friendship with Account:

[Example 7:
class SeniorAuditor : public Auditor {
public:
    double review(const Account& a) const {
        return a.balance;  // error: friendship is not inherited
    }
};

— end example]

Not transitive: a friend’s friend is not a friend. Auditor names Intern its own friend, so Intern may read Auditor’s notes, but not Account’s balance:

[Example 8:
class Auditor {
    // ...
    friend class Intern;  // Intern may read Auditor's notes
};

class Intern {
public:
    std::string notes_of(const Auditor& au) const {
        return au.notes;  // allowed: Intern is Auditor's friend
    }
    double peek(const Account& a) const {
        return a.balance;  // error: a friend's friend is not a friend
    }
};

— end example]

All four compilers rejected each line marked error with the ordinary private-access error Stranger got (for the first, naming Auditor’s notes); none has a special message about friendship. For SeniorAuditor or Intern to read balance in code of its own, Account itself would have to name it a friend; SeniorAuditor can still call the total it inherits, because that code is Auditor’s.

Account holds a private balance and the line friend class Auditor. A solid arrow runs from Auditor into balance. Crossed-out dashed arrows run from Account into Auditor’s notes, and into balance from SeniorAuditor, derived from Auditor, and from Intern, Auditor’s friend.
Figure 2 — Friendship goes one way, from the class that grants it to the class it names, and no further.

When should you use friend?

When code outside the class has to reach its private members and a public member function will not do:

  • an operator with your object on the right, such as <<
  • a class built as a pair with yours, such as a container and its iterator
  • a test that has to see the private members

Otherwise give the class a public member function and leave friend out:

[Example 9:
class Account {
public:
    explicit Account(double start) : balance(start) {}

    double get_balance() const { return balance; }  // no friend

private:
    double balance;
};

double total(const Account& a, const Account& b) {
    return a.get_balance() + b.get_balance();
}

— end example]

It printed Total: 1550.5, as the friend version did. The isocpp FAQ on friends puts the rule in one line: “Use a member when you can, and a friend when you have to.” The C++ Core Guidelines go further in C.4: “Make a function a member only if it needs direct access to the representation of a class”, which is why total is a plain function.

Does friend break encapsulation?

Not by itself. The friend list is written inside the class, so the class still decides who touches its data; the isocpp FAQ answers “No! If they’re used properly, they enhance encapsulation.” The cost is reach: each friend is more code that may have to change when the private members change, so keep the list short.

Friend class or friend function: a checklist

You need Write
One outside function that reads private data a friend function
An operator with your object on the right, such as << a friend function defined inside the class
A whole helper class that reads private data a friend class
One member function of another class a friend member function, after that class’s definition
Other code that only reads a value a public member function, no friend

More answers about the core language are in Language.

Questions

What is the difference between a friend class and a friend function?

A friend class gets access for all of its member functions: after friend class Auditor;, every function of Auditor may use the private members. A friend function is one function given the same access, declared with friend in front of it. Neither becomes a member of the class that grants the access.

Can a friend function access protected members?

Yes. The C++ standard defines a friend as a function or class given permission to name the private and protected members of the class that declares it. Public members need no friendship at all.

Does a friend function have a this pointer?

No. A friend function is not a member of the class, even when it is defined inside the class body, so it has no this. A friend reaches the objects it works on through its parameters instead.

Where do you put the friend declaration?

Anywhere inside the body of the class that grants access. Under private: or public: it means the same, because access labels have no effect on a friend declaration. The class named in friend class Auditor; does not have to be declared before that line.

Can two classes be friends of each other?

Yes, when each one declares the other a friend inside its own body. One declaration is not enough, because friendship is not mutual: it grants access in one direction only, from the class that writes it to the class it names. Define the member functions that use the other class’s members after both classes, because the first class sees the second only as declared.

Why can’t my friend function access private members?

Check that the function you defined is the one the class named. A definition whose parameters differ from the friend declaration, such as Account& where the declaration says const Account&, declares a different function that is not a friend, so its access fails with the ordinary private-member error. Copy the declaration exactly, or define the function inside the class.

Sources

  1. Friend declarationcppreference.com
  2. [class.friend] FriendsC++ standard working draft
  3. [expr.prim.this] ThisC++ standard working draft
  4. Friendsisocpp.org (C++ FAQ)
  5. C.4: Make a function a member only if it needs direct access to the representation of a classC++ Core Guidelines

Read next

  1. C++ functions: syntax, calling and overloadingLanguage · Miriam Castellanos · written for C++17
  2. C++ function pointer: syntax, callbacks and examplesLanguage · Miriam Castellanos · written for C++17
  3. C++ enum and enum class: declare, convert, switchLanguage · Miriam Castellanos · written for C++11