Skip to main content

C++ OOP

Friend Functions & Classes

Complete lesson for Friend Functions & Classes using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with C++ OOP and STL where relevant.

L1

Basics — Friend Functions & Classes

Section: C++ OOP. C++ friend functions and friend classes — selective private access, rules, and when to use them.

What is a friend in C++?

  • A **friend** is a function or class granted permission to access another class’s **private** and **protected** members.
  • Declared with the friend keyword inside the class that opens its private data.
  • Friendship is a **selective hole** in encapsulation — useful, but use carefully.
  • **Real-life:** a locked diary (private data). A friend is allowed to read it; strangers are not.
  • **Real-life:** bank vault — only authorized staff (friends) may enter, not every customer.
IdeaMeaningExample
friend functionNon-member with private accessfriend void show(const Box&);
friend classAll members of that class get accessfriend class Auditor;
Declared where?Inside the granting classIn private/public section (same effect)
Still not a memberNo this of the granting classPass objects as parameters

Friend function

  • A normal function (or another class’s member) marked friend can touch private data.
  • It is **not** called like obj.friendFunc() as a member — call it as a free function (unless it is a member of another class).
  • Often used for operators that need symmetry: operator<<, operator+ between two types.
#include <iostream>
using namespace std;

class Box {
private:
    int width, height;
public:
    Box(int w, int h) : width(w), height(h) {}
    friend void printArea(const Box& b); // friend function
};

void printArea(const Box& b) {
    cout << "Area = " << (b.width * b.height) << "\n"; // OK — friend
}

int main() {
    Box b(4, 5);
    printArea(b);
    // cout << b.width; // ERROR — private
    return 0;
}

Friend class

  • If class A { friend class B; }; then **all** member functions of B can access A’s private/protected members.
  • Useful when two types are tightly coupled (e.g. Matrix and MatrixHelper, Node and LinkedList).
  • **Real-life:** hospital Patient records — Doctor class is a friend department with full chart access.
#include <iostream>
#include <string>
using namespace std;

class Patient {
private:
    string name;
    int heartRate;
public:
    Patient(string n, int hr) : name(n), heartRate(hr) {}
    friend class Doctor;
};

class Doctor {
public:
    void checkup(const Patient& p) {
        cout << p.name << " HR=" << p.heartRate << "\n"; // OK — friend class
    }
};

int main() {
    Patient p("Ravi", 72);
    Doctor d;
    d.checkup(p);
    return 0;
}

Rules of friendship (important)

  • Friendship is **not mutual**: A friend of B does not make B friend of A automatically.
  • Friendship is **not inherited**: derived classes do not inherit friendship.
  • Friendship is **not transitive**: friend of a friend is not a friend.
  • A friend declaration can appear in any access section — access level of the declaration does not change friendship.
RuleMeaningExample thought
Not mutualOne-way grantA opens to B; B stays closed to A
Not inheritedChild ≠ friendBase friends X; Derived does not
Not transitiveNo chainA→B and B→C does not imply A→C
SelectiveYou choose exactly whoPrefer few, clear friends

Member function vs friend function

  • Both can access private data if designed that way — different calling styles and design roles.
PointMember functionFriend function
Belongs to class?YesNo (usually free function)
Has this?YesNo (unless member of another class)
Call styleobj.f()f(obj) or a + b
Private accessYes (own class)Yes if declared friend
Good forObject behaviourSymmetric operators, helpers

Classic use — operator<< as friend

  • Left operand of << is usually ostream&, not your class — so a member operator<< on your class is awkward.
  • A **friend** (or free function with public getters) lets you write cout << obj;.
  • Prefer getters when they are enough; use friend when you need deep private access cleanly.
#include <iostream>
#include <string>
using namespace std;

class Student {
private:
    int roll;
    string name;
public:
    Student(int r, string n) : roll(r), name(n) {}
    friend ostream& operator<<(ostream& os, const Student& s);
};

ostream& operator<<(ostream& os, const Student& s) {
    os << s.roll << " " << s.name;
    return os;
}

int main() {
    Student s(101, "Asha");
    cout << s << "\n";
    return 0;
}

When to use friend (and when not)

  • Friends weaken encapsulation — grant them only when the design truly needs private access.
SituationPreferWhy
Symmetric binary operatorsFriend / free functionNatural a + b / cout << a
Tight helper of one classFriend function/classNeeds internals
Normal behaviour of objectPublic member functionKeeps encapsulation
Just reading a fieldPublic getterNo need for friend
Many outsiders need dataRethink APIToo many friends = leaky design
L2

Advanced — Friend Functions & Classes

Friend member function of another class

  • You can friend a **specific** member function: friend void Other::peek(const My&);
  • Requires careful declaration order / forward declarations.
  • Narrower than friending the whole class — better for encapsulation.

Forward declarations and friend

  • Often you forward-declare a class before friending it: class Auditor; class Account { friend class Auditor; ...};
  • Circular friendships need careful header structure.
class Doctor; // forward declaration

class Patient {
    int id;
    friend class Doctor;
public:
    Patient(int i) : id(i) {}
};

Friendship and encapsulation trade-off

  • Every friend is an exception to data hiding.
  • Document why friendship exists.
  • If many friends appear, the class may need a better public interface or to split responsibilities.
  • Operators and tightly coupled containers/nodes are the most accepted friend uses.

Common pitfalls

  • Assuming friendship is mutual or inherited — it is not.
  • Friending an entire class when one function would do.
  • Using friend to avoid writing a clean API.
  • Forgetting that friend functions still need proper declarations/definitions.

Real-life models

  • Hospital: Patient friends Doctor.
  • Bank: Account friends Auditor for inspection.
  • Game: GameObject friends PhysicsEngine for private transform access.
  • Containers: List friends ListIterator / node helpers.
L3

Tricky Interview Points

Q1) What is a friend function?

Answer A non-member function granted access to a class’s private and protected members via a friend declaration inside that class.

Q2) What is a friend class?

Answer A class whose member functions can access another class’s private/protected members because it was declared as a friend.

Q3) Is friendship mutual?

Answer No. If A declares B as a friend, B does not automatically become able to have A as a friend the other way.

Q4) Is friendship inherited?

Answer No. Friendship is not inherited by derived classes.

Q5) Is friendship transitive?

Answer No. Friend of a friend is not automatically a friend.

Q6) Why use friend for operator<<?

Answer Because the left operand is typically ostream, so a free/friend function fits naturally for cout << obj while allowing private access if needed.

Q7) Does a friend function have a this pointer of the granting class?

Answer No. It is not a member of that class, so it receives objects as explicit parameters.

Q8) Where should friend be declared?

Answer Inside the class that grants access. The access section (private/public) does not change the friendship grant.

Q9) When should you avoid friends?

Answer When a public method or getter is enough, or when many friends would punch too many holes in encapsulation.

Q10) Member function vs friend function?

Answer Members are part of the class and use this; friends are outside (usually) but can access privates if granted. Friends are handy for symmetric operators.

Q11) Can we friend only one member function of another class?

Answer Yes — you can declare a specific Other::func as friend instead of the whole class.

Q12) Give a real-life analogy for friend.

Answer A locked diary that only named friends may read; friendship is granted by the owner and is not automatically two-way.

L4

Simple Programs

Friend function — print private data

#include <iostream>
using namespace std;

class Secret {
private:
    int code;
public:
    Secret(int c) : code(c) {}
    friend void reveal(const Secret& s);
};

void reveal(const Secret& s) {
    cout << "code = " << s.code << "\n";
}

int main() {
    Secret s(42);
    reveal(s);
    return 0;
}

Friend class — Doctor / Patient

#include <iostream>
#include <string>
using namespace std;

class Patient {
    string name;
    int hr;
public:
    Patient(string n, int h) : name(n), hr(h) {}
    friend class Doctor;
};

class Doctor {
public:
    void report(const Patient& p) {
        cout << p.name << ": " << p.hr << " bpm\n";
    }
};

int main() {
    Patient p("Neha", 78);
    Doctor().report(p);
    return 0;
}

Friendship is not mutual

#include <iostream>
using namespace std;

class A {
private:
    int x = 1;
public:
    friend class B; // B may access A
};

class B {
private:
    int y = 2;
public:
    void showA(const A& a) { cout << a.x << "\n"; } // OK
    // A cannot access y unless B also declares friend class A;
};

int main() {
    A a; B b;
    b.showA(a);
    return 0;
}

operator<< as friend

#include <iostream>
using namespace std;

class Point {
    int x, y;
public:
    Point(int a, int b) : x(a), y(b) {}
    friend ostream& operator<<(ostream& os, const Point& p);
};

ostream& operator<<(ostream& os, const Point& p) {
    return os << "(" << p.x << "," << p.y << ")";
}

int main() {
    Point p(2, 3);
    cout << p << "\n";
    return 0;
}

Compare — getter vs friend

#include <iostream>
using namespace std;

class Temp {
private:
    int c = 25;
public:
    int getC() const { return c; }
    friend void showFriend(const Temp& t);
};

void showFriend(const Temp& t) { cout << t.c << "\n"; }
void showGetter(const Temp& t) { cout << t.getC() << "\n"; }

int main() {
    Temp t;
    showFriend(t);
    showGetter(t);
    return 0;
}

Binary friend operator+

#include <iostream>
using namespace std;

class Vec2 {
    int x, y;
public:
    Vec2(int a, int b) : x(a), y(b) {}
    friend Vec2 operator+(const Vec2& a, const Vec2& b);
    void show() const { cout << x << "," << y << "\n"; }
};

Vec2 operator+(const Vec2& a, const Vec2& b) {
    return Vec2(a.x + b.x, a.y + b.y);
}

int main() {
    Vec2 u(1, 2), v(3, 4);
    Vec2 w = u + v;
    w.show(); // 4,6
    return 0;
}
L5

Problem Solving Tricks

  • friend grants private/protected access — a controlled exception to encapsulation.
  • Remember: not mutual, not inherited, not transitive.
  • Prefer friending one function over an entire class when possible.
  • operator<< / symmetric operators are classic friend use cases.
  • If a getter is enough, skip friend.
  • Friends are not members — no this of the granting class.
  • Document why each friend exists.
  • Too many friends ⇒ redesign the public API.
  • Forward-declare classes involved in friendship when needed.
  • Friend declaration’s private/public section does not limit the grant.
  • Use const references in friend helpers that only read.
  • Diary/vault analogies work well in interviews.
L6

Practice Programs List

  1. Write a Box class with private width/height and a friend printArea function.
  2. Create Patient and friend class Doctor that prints private vitals.
  3. Demonstrate that friendship is not mutual with two small classes.
  4. Implement operator<< as a friend for a Student class.
  5. Implement operator+ as a friend for a Complex or Vec2 class.
  6. Refactor a friend that only reads one field into a public getter instead.
  7. Friend a single member function of another class (advanced ordering exercise).
  8. Explain in comments the three friendship rules with tiny examples.
  9. Build Account with friend Auditor::inspect.
  10. Compare member display() vs friend display(obj) calling styles.
  11. List five designs where friend is justified and five where it is not.
  12. Show a compile error when a non-friend tries to access private data.
  13. Write LinkedList friending Node (or vice versa) for a mini list demo.
  14. Discuss encapsulation trade-offs of your friend usage in comments.