Implementing Custom Operator Behavior in C++

Operator overloading enables user-defined types to utilize built-in operators with customized functionality. Without explicit overloading, class objects cannot leverage these operators directly. The mechanism involves defining special member functions where the function name uses the operator keyword followed by the symbol.

Core Concepts

1. Overloading redefines operator behavior for specific types, implemented as class member functions

2. Syntax: ReturnType operator Symbol(Parameters)

3. Parameter count depends on the operator's arity (unary/binary)

4. The left operand invokes the overloaded operator function

5. Return types and parameters should follow conventional usage patterns

Arithmetic Operatro Implemantation

#include <iostream>
class ComplexNum {
    double real, imag;
public:
    ComplexNum(double r, double i) : real(r), imag(i) {}
    
    ComplexNum operator+(const ComplexNum& rhs) const {
        return ComplexNum(real + rhs.real, imag + rhs.imag);
    }
    
    void display() const {
        std::cout << real << " + " << imag << "i\n";
    }
};

int main() {
    ComplexNum a(3.5, 2.1);
    ComplexNum b(1.2, 4.7);
    ComplexNum result = a + b;
    result.display();
}

Comparison Operator Overloading

#include <iostream>
class Temperature {
    double celsius;
public:
    Temperature(double c) : celsius(c) {}
    
    bool operator>=(const Temperature& other) const {
        return celsius >= other.celsius;
    }
};

int main() {
    Temperature t1(37.5);
    Temperature t2(40.0);
    std::cout << (t2 >= t1) << std::endl;
}

Assignment Operator Implementation

Note: Compilers generate default assignment operators that perform member-wise copying

class Buffer {
    char* data;
    size_t size;
public:
    Buffer(size_t sz) : size(sz), data(new char[sz]) {}
    
    Buffer& operator=(const Buffer& source) {
        if (this != &source) {
            delete[] data;
            size = source.size;
            data = new char[size];
            std::copy(source.data, source.data + size, data);
        }
        return *this;
    }
    
    ~Buffer() { delete[] data; }
};

Subscript Operator Customization

class IntVector {
    int* elements;
    size_t capacity;
public:
    IntVector(size_t cap) : capacity(cap), elements(new int[cap]) {}
    
    int& operator[](size_t index) {
        if (index >= capacity) throw std::out_of_range("Invalid index");
        return elements[index];
    }
    
    const int& operator[](size_t index) const {
        if (index >= capacity) throw std::out_of_range("Invalid index");
        return elements[index];
    }
};

Stream Insertion Operator

#include <iostream>
class Measurement {
    double value;
public:
    Measurement(double v) : value(v) {}
    
    friend std::ostream& operator<<(std::ostream& os, const Measurement& m);
};

std::ostream& operator<<(std::ostream& os, const Measurement& m) {
    return os << m.value << " units";
}

int main() {
    Measurement m(15.3);
    std::cout << m << std::endl;
}

Non-Overloadable Operators

  • Ternary conditional (?:)
  • Scope resolution (::)
  • Member access (.)
  • Member pointer (.*)
  • sizeof operator

Tags: Operator Overloading C++ Classes Custom Operators class methods Stream Operators

Posted on Mon, 14 Sep 2026 16:31:17 +0000 by MikeNye