CSS Prepare

optional · CSS study notes

Operator Overloading (extended)

  • Operator overloading: redefining the behavior of an existing operator (+, -, ==, <<, etc.) for a user-defined type, so objects can use natural operator syntax instead of a named function call
  • Implemented as a member function — ReturnType operator@(Args), where the left operand is the implicit calling object — or as a non-member / friend function, needed when the left operand isn't an object of your class (e.g. cout << obj)
  • Unary operator overloading (one operand, e.g. -x, ++x, x++) vs binary operator overloading (two operands, e.g. x + y) — different parameter counts/signatures
  • Stream insertion (<<) / extraction (>>): must be overloaded as non-member/friend functions, since the left operand (cout/cin) is not an object of your class
  • Operators that cannot be overloaded in C++: :: (scope resolution), . (member access), .* (pointer-to-member), ?: (ternary), sizeof — common MCQ trap
  • Copy constructor and assignment operator (operator=) are special, heavily tested overloads — critical whenever a class manages dynamic memory (the "Rule of Three": defining one of destructor / copy constructor / copy-assignment operator usually means you need all three)

C++ Example — Overloading + and << for a Complex Class

class Complex
{
private:
    double real, imag;

public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}

    // member function: overloads binary +
    Complex operator+(const Complex& other) const
    {
        return Complex(real + other.real, imag + other.imag);
    }

    // friend function: overloads << (left operand is ostream, not Complex)
    friend ostream& operator<<(ostream& out, const Complex& c)
    {
        out << c.real << " + " << c.imag << "i";
        return out;
    }
};

int main()
{
    Complex a(2, 3), b(1, 4);
    Complex c = a + b;   // calls operator+  instead of a named add() function
    cout << c;            // calls operator<< -- prints "3 + 7i"
}

Why Overload the Copy Constructor? Shallow vs Deep Copy

class Buffer
{
private:
    int* data;

public:
    Buffer(int size) { data = new int[size]; }

    // Deep copy constructor -- allocates its OWN memory
    Buffer(const Buffer& other)
    {
        data  = new int[1];
        *data = *other.data;
    }
    // Without an explicit deep-copy version, the compiler-generated
    // copy constructor does a SHALLOW copy: both objects' 'data'
    // point to the SAME memory, so destroying one leaves the other
    // with a dangling pointer -- a classic CSS exam pitfall.

    ~Buffer() { delete[] data; }
};

MCQ Trap

  • operator<< / operator>> cannot be overloaded as ordinary member functions of your own class — the left-hand operand must be ostream/istream, so they must be friend/non-member functions
  • Overloading an operator only changes its behavior for your type — it can never change its precedence, associativity, or number of operands