Skills101

C++ Programming · Lesson 5 of 9 · Updated ·

Operator Overloading, friend Functions and Templates in C++

C++ lets your own types behave like built-in ones (a + b, cout << a) and lets you write code once that works for any type.

1. Operator overloading

#include <iostream>
using namespace std;

class Money {
    long paise;
public:
    explicit Money(long rupees, long p = 0) : paise(rupees * 100 + p) {}
    Money operator+(const Money &o) const { Money m(0); m.paise = paise + o.paise; return m; }
    bool operator==(const Money &o) const { return paise == o.paise; }
    bool operator<(const Money &o) const { return paise < o.paise; }
    friend ostream &operator<<(ostream &out, const Money &m);
};

ostream &operator<<(ostream &out, const Money &m) {
    return out << "Rs " << m.paise / 100 << "." << (m.paise % 100 < 10 ? "0" : "") << m.paise % 100;
}

int main() {
    Money a(199, 50), b(300, 75);
    cout << a + b << " " << (a == b) << " " << (a < b) << "\n";
    return 0;
}
Rs 500.25 0 1
  • operator+ as a member takes the right-hand side as the parameter (this is the left side).
  • operator<< must be a non-member (the left side is ostream), so it's declared friend to read private data.
  • Overload operators only when the meaning is obvious (+ for money is fine; + that deletes a file is not).

Operators you can't overload: ::, ., .*, ?:, sizeof.

2. friend functions and classes

A friend can access a class's private members. Use it sparingly — mainly for operators like << and closely related helper classes. Friendship is not inherited and not mutual.

3. Function templates

A function template biggest(T a, T b) works for ints, doubles and strings: biggest(3, 9) gives 9, biggest(2.5, 1.5) gives 2.5, and with strings gives "pune"

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

template <typename T>
T biggest(T a, T b) { return a > b ? a : b; }

template <typename T>
void printAll(const T &items) {
    for (const auto &x : items) cout << x << " ";
    cout << "\n";
}

int main() {
    cout << biggest(3, 9) << " " << biggest(2.5, 1.5) << " " << biggest(string("pune"), string("agra")) << "\n";
    int marks[] = {70, 85, 92};
    printAll(marks);
    return 0;
}
9 2.5 pune
70 85 92

The compiler generates a separate version for each type you use (instantiation), so templates are as fast as hand-written code.

4. Class templates

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

template <typename T>
class Box {
    T value;
public:
    explicit Box(T v) : value(v) {}
    T get() const { return value; }
    bool isBiggerThan(const Box<T> &o) const { return value > o.value; }
};

int main() {
    Box<int> a(42), b(7);
    Box<string> name("Skills101");
    cout << a.get() << " " << a.isBiggerThan(b) << " " << name.get() << "\n";
    return 0;
}
42 1 Skills101

vector<int>, map<string, int> and the whole STL (next lesson) are class templates.

Common mistakes

  • Making operator<< a member function (it can't be — the left operand is the stream).
  • Forgetting to return the stream (return out;), which breaks chaining.
  • Putting template definitions in a .cpp file — templates usually live entirely in headers.

Quick recap

  • Overload operators as members (a + b → a.operator+(b)) or non-members (<<).
  • friend gives a function access to private data; use sparingly.
  • Function and class templates: write once, the compiler generates per type.
  • The STL is built from templates.

Practice what you learned

📝 Quiz: Operators and Templates5 questions · instant answers & explanations · +10 XP · counts towards your free certificateTake the quiz →