Siksha Sarovar

Siksha Sarovar (sikshasarovar.com) is a free educational web application that helps students in India learn programming and prepare for academic and competitive exams. The platform offers structured coding courses (C, C++, Python, Java, HTML, CSS, PHP, Power BI, AI, Machine Learning, Data Science), complete university curriculum notes for BCA/MCA students with previous year question papers, Class 10 and Class 12 CBSE/HBSE school notes, and dedicated preparation material for SSC, UPSC, Banking, Railway and other government exams. Browsing the site is completely free and requires no account. Users may optionally sign in with Google solely to save their learning progress, quiz scores and personal preferences across devices.

Privacy Policy | Terms of Service | Contact Siksha Sarovar | About Siksha Sarovar

v4.0.9 · PWA
Siksha Sarovar logo
Siksha Sarovar
Your Learning Universe

Siksha Sarovar is a free e-learning platform for coding courses, BCA university notes and competitive exam preparation. Optional Google sign-in saves your learning progress across devices.

Initializing knowledge base…
Compiling modules 0%

2.2 Function Overloading, Static Members, Friend & this Pointer

Lesson 9 of 22 in the free Object Oriented Programming with C++ notes on Siksha Sarovar, written by Rohit Jangra.

2.2 Function Overloading, Static Members, Friend & this Pointer

Function Overloading in Classes

Already introduced in Unit I — within a class, you can overload constructors and member functions:

class Calculator {
public:
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }
    int add(int a, int b, int c) { return a + b + c; }
};

Calculator c;
c.add(2, 3);          // int version
c.add(2.5, 3.5);      // double version
c.add(1, 2, 3);       // 3-arg version

Common uses

  • Multiple constructor signatures (default, parameterized, copy)
  • Operations on different types
  • Variants of print / display / set

---

Static Data Members

A static data member belongs to the class itself, not to any object. All objects share the same copy.

class Counter {
private:
    static int count;       // declaration

public:
    Counter() { count++; }
    static int getCount() { return count; }
};

int Counter::count = 0;     // definition — required outside the class

int main() {
    Counter a, b, c;        // 3 objects created
    cout << Counter::getCount();   // 3
    return 0;
}

Key rules

  • Declared inside the class with static
  • Defined outside the class with ClassName::name
  • One copy per class, not per object
  • Can be accessed via ClassName::member (preferred) or object.member
  • Initialised before main() starts
  • const static integral types can be initialised in-class:
class Config {
    static const int MAX = 100;    // OK for const static int
};

Common uses

  • Counter — how many objects exist
  • Shared resource — connection pool
  • Configuration — max size, default values
  • Singleton pattern — single instance

---

Static Member Functions

A static member function belongs to the class, not to any object. It can be called without an instance.

class Math {
public:
    static int square(int x) { return x * x; }
    static const double PI;
};

const double Math::PI = 3.14159;

int main() {
    cout << Math::square(5);   // 25 — no object needed
    cout << Math::PI;          // 3.14159
    return 0;
}

Restrictions

  • Cannot access non-static members (no this pointer)
  • Cannot be virtual
  • Cannot be const (no object to be const)
class A {
    int x;                          // non-static
    static int y;                   // static

    static void f() {
        // x = 5;     ERROR — no 'this'
        y = 5;        // OK — y is static
    }
};

Use cases

  • Utility / helper functions (Math::sqrt)
  • Factory functions (Student::create(...))
  • Singleton accessor

---

this Pointer

The this pointer is an implicit pointer to the current object inside any non-static member function.

class Student {
private:
    int id;
    string name;

public:
    void setData(int id, string name) {
        this->id = id;        // 'this->id' = data member; 'id' = parameter
        this->name = name;
    }

    Student& self() {
        return *this;         // return reference to current object
    }
};

Why this exists

Every non-static member function receives a hidden first parameter: a pointer to the object on which it was called. Inside the function, this is that pointer.

s.setData(101, "Rohit");
// Compiler treats it as: setData(&s, 101, "Rohit");
// Inside: this == &s

Common uses of this

1. Disambiguating parameters from data members

void Student::setId(int id) {
    this->id = id;      // 'this->' clarifies that left side is member
}

2. Method chaining (fluent interface)

class Builder {
public:
    Builder& setName(string n) { name = n; return *this; }
    Builder& setAge(int a) { age = a; return *this; }
private:
    string name;
    int age;
};

Builder b;
b.setName("Rohit").setAge(20);   // chain

3. Returning self from operators

A& A::operator=(const A& other) {
    // copy logic
    return *this;
}

4. Passing self to a function

class A {
public:
    void method() {
        external_function(this);   // pass own address
    }
};

Inside static functions

this does not exist in static functions — they have no associated object.

---

Friend Functions

A friend function is a non-member function that has been granted access to a class's private and protected members.

class Distance {
private:
    int feet;
    double inches;

public:
    Distance(int f, double i) : feet(f), inches(i) {}

    friend void displayDistance(Distance d);   // declaration
};

void displayDistance(Distance d) {
    cout << d.feet << " ft " << d.inches << " in" << endl;
    // 'd.feet' and 'd.inches' are private — but accessible because friend
}

int main() {
    Distance d(5, 6.5);
    displayDistance(d);
    return 0;
}

Characteristics of friend functions

  • Declared inside the class with friend keyword
  • Defined like a regular function (not a member function)
  • Has no this pointer
  • Accesses private/protected members of the friend class
  • Called like a regular function — f(d), not d.f()
  • Friendship is not inherited or transitive

When to use friend functions

  • Operator overloading for asymmetric operations (e.g., int + Distance)
  • Helper functions that need access to internals but logically aren't members
  • Bridging two classes that need shared access

Disadvantages

  • Breaks encapsulation — friend functions see private internals
  • Use sparingly — overuse defeats the purpose of OOP

---

Friend Class

An entire class can be declared a friend, granting all its member functions access:

class Account;   // forward declaration

class BankManager {
public:
    void audit(Account& a);
};

class Account {
private:
    double balance;
    friend class BankManager;   // BankManager has access to private
};

void BankManager::audit(Account& a) {
    cout << "Balance: " << a.balance;  // OK
}

Properties of friendship

  • Friendship is granted, not taken — A declares B as friend
  • Not symmetric — A friend of B does not mean B friend of A
  • Not transitive — friend of friend is not automatically friend
  • Not inherited — derived classes don't inherit friend relationships

---

Friend Member Function (a single member, not whole class)

class B;

class A {
public:
    void access(B& b);   // wants to access B's privates
};

class B {
private:
    int data;
    friend void A::access(B& b);   // only this one member is friend
};

void A::access(B& b) {
    cout << b.data;   // OK
}

---

Member Function vs Friend Function — exam table

AspectMember FunctionFriend Function
Declared inside classYesYes (with friend)
Member of classYesNo
Has this pointerYesNo
Called asobj.func()func(obj)
Access private membersYesYes
InheritedYesNo
Can be virtualYesNo
Defined inside class?OftenNo (just declared)

---

Putting It All Together — Counter Class

class Counter {
private:
    int value;
    static int totalCounters;       // static — shared count

public:
    Counter() : value(0) {
        totalCounters++;
    }

    ~Counter() {
        totalCounters--;
    }

    void increment() { value++; }

    Counter& reset() {
        value = 0;
        return *this;                // return self — chaining
    }

    int getValue() const { return value; }

    static int getTotal() {           // static — no object needed
        return totalCounters;
    }

    friend ostream& operator<<(ostream& os, const Counter& c);
};

int Counter::totalCounters = 0;       // definition

ostream& operator<<(ostream& os, const Counter& c) {
    os << "Counter: " << c.value;     // accesses private via friend
    return os;
}

int main() {
    Counter c1, c2;
    c1.increment(); c1.increment();
    cout << c1 << endl;               // Counter: 2
    cout << "Total: " << Counter::getTotal();  // 2
    return 0;
}

---

Study deep

  1. Static members live in the data segment, not on the heap or stack. They're initialised before main() and destroyed after. The single definition outside the class allocates the storage.
  1. this pointer is the difference between member and free function. In a sense, obj.f() is just syntactic sugar for f(&obj). The dot syntax makes the receiver explicit and enables OO design.
  1. Friend functions trade encapsulation for convenience. They're useful — especially for operator overloading where the left operand isn't your class. But every friend declaration is a hole in your encapsulation; use sparingly.
  1. Static + const + integral = compile-time constant. static const int MAX = 100; inside a class is a compile-time constant the compiler can inline. Modern alternative: static constexpr int MAX = 100;.
  1. **Method chaining via return this.* A common modern idiom — builders, configurations, custom streams. The "fluent" style is more readable than separate statements.

Key Terms — Lesson 2.2

The terms below cover function overloading inside classes, static members, friends, and the this pointer — the dense core of Unit II.

Function Overloading (in Classes) — As with free functions, classes can have multiple member functions with the same name but different parameter lists. The compiler picks the right overload at the call site. Operator overloading (Unit III) is a special case of function overloading.

Static Data Member — A data member declared with static that belongs to the class itself, not to any individual object — all objects share the same copy. Used for counters, configuration, shared resources. Must be defined outside the class (int Counter::totalCounters = 0;) — the in-class declaration is not a definition.

Static Member Function — A member function declared with static that belongs to the class itself. Called via the class name (ClassName::method()) without needing an object. Has no this pointer and therefore cannot access non-static members directly.

this Pointer — An implicit pointer available inside every non-static member function, pointing to the object on which the function was called. Lets the function reference the current object's members and disambiguate them from parameters with the same name (this->id = id;).

**Self-Reference (this) — Dereferencing the this pointer gives the current object itself*. return *this; returns a reference to the current object, enabling method chaining (obj.reset().increment().display()).

Method Chaining / Fluent Interface — A design idiom where each method returns a reference to the same object, letting calls be chained on one line. The builder pattern, jQuery, LINQ, and many testing libraries use fluent interfaces.

Friend Function — A non-member function declared with the friend keyword inside a class, gaining access to the class's private and protected members. Friend functions are not methods (no this pointer, called like ordinary functions, no implicit object) but bypass access restrictions. Common use: overloading binary operators where the left operand is not the class.

Friend Class — An entire class declared as friend of another. Every member function of the friend class gains access to the host class's private and protected members. Useful for tightly-coupled class pairs (LinkedList and Node, Iterator and Container).

Mutual Friendship — Two classes that friend each other can each access the other's private members. Useful but indicates tight coupling — usually a signal that the design might be cleaner with a single class or composition.

Encapsulation vs Friendship — Friend declarations are deliberate holes in encapsulation. They're not a violation per se — the class itself controls who is a friend — but every friend declaration should be defensible. Modern advice: prefer member functions or public interface where possible.

Static vs Non-Static Members — Two member categories with different lifetimes and semantics. Non-static members are per-object — each object has its own copy, accessed via the object (obj.field). Static members are per-class — one copy shared across all objects, accessed via the class (Class::field).

Friend Function Characteristics — A friend function (1) is declared inside the class with friend keyword, (2) is not a member of the class, (3) has no this pointer, (4) is called as a free function (not on an object), (5) can access private and protected members of the host class, (6) is not inherited by derived classes.

mutable Keyword — A modifier that lets a data member be modified even inside a const member function. Used for caches, lazy initialisation counters, mutexes — members that don't logically affect the object's externally-visible state.

Stream Insertion via Friend — The classic friend-function use case: overloading operator<< for a custom class. Because the left operand is ostream (not your class), operator<< cannot be a member of your class — making it a friend gives it access to private members.

static const / static constexpr Member — A static data member that is also const or constexpr. static const int (and constexpr) can be initialised in-class if integral; static constexpr can be initialised in-class for any literal type. Used for compile-time class-level constants (Class::MAX_SIZE).

Class-Level vs Instance-Level Methods — A categorisation borrowed from Java/Python vocabulary that maps to static vs non-static member functions. Class-level (static) methods don't need an object and serve as utility functions tied to the class. Instance-level (non-static) methods operate on a specific object.

Operator Overloading (Preview) — Friend functions are commonly used to overload binary operators where the left operand is not the user's class — operator<< (for cout), operator+ between built-in types and user types, etc. Detailed in Unit III.

---

PYQ pattern (very common): "What is the this pointer? Explain with example." — Define as implicit pointer to current object; show disambiguation example; show method chaining; mention that static functions don't have this.
PYQ pattern: "What is a friend function? List its characteristics." — Define; 5-6 characteristics (declared inside class, not member, no this, called as function, can access private, not inherited); compare with member function.
PYQ pattern: "Differentiate static and non-static member functions / data members." — Static = belongs to class, shared across objects, no this, accessible via ClassName::; non-static = per-object.