Theory
The auditor's problem
The college sends an auditor to verify the canteen's books. The till's cash is private, exactly as it should be.
But the auditor is not a member function of CanteenTill: audits must stay outside the class they inspect, or the inspection means nothing.
So the question: how does an outside function read cash without making cash public for the whole world? C++ answers with a keyword that sounds friendly and behaves like a signed gate pass: friend.
Theory
The gate pass
The owner writes a note and pins it inside the office: "The auditor Mr. Desai may open the cash drawer."
Note three things: the owner issued the pass (not the auditor demanding one), the pass names one person (not all visitors), and Mr. Desai still works outside the canteen: the pass does not make him staff.
That is a friend declaration: access granted by the class, to a named outsider, who stays an outsider.
Theory
Friend function, formally
A friend function is a non-member function that a class authorizes to access its private and protected members.
- Declared inside the class with the
friendkeyword. - Defined outside like a normal function: no
ClassName::prefix, nofriendkeyword at the definition. - Not called with the dot operator: it takes the object as a parameter and reaches inside it.
The declaration may sit in the public or private section; its position changes nothing.
Practical
The audit gate pass in code
#include <iostream>
using namespace std;
class CanteenTill {
private:
double cash;
public:
CanteenTill(double opening) { cash = opening; }
// the gate pass: audit() may read private members
friend void audit(CanteenTill t);
};
// defined outside: no CanteenTill::, no friend keyword here
void audit(CanteenTill t) {
cout << "Audited balance: " << t.cash << endl; // legal: friend
}
int main() {
CanteenTill till(500.0);
audit(till); // ordinary call, NOT till.audit()
return 0;
}
Think first
Member or not?
The declaration friend void audit(CanteenTill t); sits INSIDE the class body. Before tapping: is audit() a member function of CanteenTill? And how would main() call it: audit(till) or till.audit()?
Show the answer
Not a member. The friend keyword marks it as an outsider being granted access; being written inside the class body is only where the grant is recorded. Therefore main() calls it as an ordinary function: audit(till). Writing till.audit() is a compile error, and "declared inside, yet not a member" is precisely the exam's favourite friend-function trick.
Quiz
audit() is a friend of CanteenTill. StaffTill is derived from CanteenTill. Can audit() access StaffTill's own private members?
- No: friendship is not inherited by derived classes
- Yes: friends of the base are friends of every child
- Yes, but only the protected members
- Only if StaffTill is in the same file
Show the answer
No: friendship is not inherited by derived classes
Friendship is personal to the class that granted it: it is not inherited, not mutual, and not transitive. StaffTill would have to issue its own friend declaration. (audit() could still reach the CanteenTill-part inherited inside a StaffTill object, but StaffTill's own private additions stay closed.) Option B is the misconception; file placement never affects access.
Watch out
Handle with care
Every friend function is a small hole drilled through encapsulation. Exams expect you to say so: "friend functions should be used sparingly because they bypass data hiding."
Also be precise in definitions: friendship is granted by the class in its own body. A function cannot declare itself a friend from outside, otherwise private would mean nothing.
Theory
When a friend is the right tool
The honest use case: an operation that needs the private data of two different classes at once, like comparing a CanteenTill's cash with a BankRecord's entry. Neither class is the natural home for that function, so both declare it a friend. Operator overloading also leans on friends (letting cout << till read private members). One function, two gate passes: perfectly legal.
Summary
Key takeaways
- A friend function is a NON-member granted access to private/protected members.
- Declared inside the class with friend; defined outside with no :: and no friend keyword.
- Called like an ordinary function with the object as a parameter, never with the dot.
- Friendship is granted by the class; it is not inherited, not mutual, not transitive.
- Use sparingly: each friend bypasses data hiding.
- Classic use: one function needing privates of two classes; operator overloading.
- Memory hook: a gate pass, not a staff badge.