C, C++, MFC  

Chapter 13: Operator Overloading and Friend Functions in C++

Previous chapter: Chapter 12: Polymorphism: Virtual Functions and Abstract Classes in C++

Operator overloading allows C++ programmers to redefine the behavior of most standard operators (like +, -, ==) when applied to user-defined types (classes). This makes working with objects intuitive and readable.

1. Operator Overloading: Making Classes Intuitive

The goal of overloading is to make class syntax resemble built-in types. For example, we can make two Vector objects add together using the standard + symbol.

Overloading Binary Operators (e.g., +)

To overload an operator, you define a function named operator@ (where @ is the operator symbol).

class Vector {
private:
    int x, y;

public:
    Vector(int a, int b) : x(a), y(b) {}

    // Overloading the '+' operator
    Vector operator+(const Vector& other) const {
        return Vector(x + other.x, y + other.y);
    }
};

int main() {
    Vector v1(1, 2);
    Vector v2(3, 4);
    Vector v3 = v1 + v2; // Calls v1.operator+(v2)
    // v3 is now (4, 6)
    return 0;
}

Overloading Unary Operators (e.g., ++)

Unary operators only work on one operand.

class Counter {
    // ...
public:
    // Overloading the Prefix Increment Operator (e.g., ++c)
    Counter& operator++() {
        // logic to increment internal value
        return *this; // Returns a reference to the modified object
    }
    // ...
};

2. Overloading Stream Operators (<< and >>)

The most common and useful overloads are the stream insertion (<<) and extraction (>>) operators, which allow your objects to be used seamlessly with std::cout and std::cin. These are typically implemented as non-member functions.

// Non-member function signature for cout (insertion)
std::ostream& operator<<(std::ostream& os, const Vector& v) {
    os << "Vector(" << v.x << ", " << v.y << ")";
    return os;
}

3. Friend Functions and Friend Classes

A challenge with non-member operator functions is accessing private data members (like v.x and v.y).

A friend function is a non-member function that is granted special permission to access the private and protected members of a class. The declaration is done inside the class definition, prefixed with the keyword friend.

class Vector {
private:
    int x, y;
    // Grant access to the output operator function
    friend std::ostream& operator<<(std::ostream& os, const Vector& v);
public:
    Vector(int a, int b) : x(a), y(b) {}
    // ...
};

Similarly, a friend class grants all its member functions access to the private and protected members of the class declaring the friendship.