Namespaces
Variants
Actions

Operator overloading in C++

From cppreference.com


Operator overloading in C++ allows us to write natural expressions like d = a + b / c; with our own classes. The above expression could be equal to d = a.add(b.divide(c)); which results in hard to read code.

Operator overloading by Example

This example will add basic arithmetic operations: addition, subtraction, multiplication and division to Complex number class. These operations will use operators: +, -, *, / and their assigning counterparts +=, -=, *=, /=. Only addition will be implemented.

We will also add input/output operators to read/write from/to standard input/output. Both operators are free functions (and not class methods). Input operator operator<< takes two arguments: a reference to an input stream and a constant reference to object to write, and returns a reference to the input stream. Output operator operator>> takes two arguments: a reference to an output stream and a reference to object to write, it returns as well a reference to the output stream.

#include <iostream>
#include <sstream>
 
template <typename T = double>
class Complex
{
public:
    typedef T value_type;
    Complex() 
        : m_real(T())
        , m_imag(T())
    {}
 
    Complex(T const& real, T const& imag)
        : m_real(real)
        , m_imag(imag)
    {}
 
    T& real()
    {
        return m_real;
    }
    T const& real() const
    {
        return m_real;
    }
    T& imag()
    {
        return m_imag;
    }
    T const& imag() const
    {
        return m_imag;
    }
 
    /// constructor
    Complex(Complex<T> const& other) = default;
    /// destructor
    virtual ~Complex() = default;
 
    // assignment operator, generated by compiler
    Complex<T>& operator=(Complex<T> const& other) = default;
 
    // addition
    Complex<T> operator+(Complex<T> const& rhs) const;    // this could be a template method with any Complex<S> convertible to Complex<T>
    Complex<T>& operator+=(Complex<T> const& rhs);
 
    // subtraction
    Complex<T> operator-(Complex<T> const& rhs) const;
    Complex<T>& operator-=(Complex<T> const& rhs);
 
    // multiplication
    Complex<T> operator*(Complex<T> const& rhs) const;
    Complex<T>& operator*=(Complex<T> const& rhs);
 
    // division
    Complex<T> operator/(Complex<T> const& rhs) const;
    Complex<T>& operator/=(Complex<T> const& rhs);
 
private:
    value_type m_real;
    value_type m_imag;
};
 
template <typename T>
Complex<T> Complex<T>::operator+(Complex<T> const& rhs) const
{
    Complex<T> result = *this;
    result += rhs;
    return result;
}
 
template <typename T>
Complex<T>& Complex<T>::operator+=(Complex<T> const& rhs)
{
    m_real += rhs.m_real;
    m_imag += rhs.m_imag;
    return *this;
}
 
template <typename T>
std::ostream& operator<<(std::ostream& os, Complex<T> const& obj)
{
    // output (real_part + imaginary_part"i")
    os << "(" << obj.real() << " + " << obj.imag() << "i)";
    return os;
}
 
template <typename T>
std::istream& operator>>(std::istream& is, Complex<T>& obj)
{
    // does not check std::istream::fail()
    typedef char CharT;
    CharT c;
 
    is >> std::ws; // skip whitespaces
    is >> c;
    // should start with opening parenthesis '('
    if (c != '(') {
        is.setstate(std::ios_base::failbit);
        return is;
    }
    is >> std::ws; // skip whitespaces
    is >> obj.real(); // read real part
    is >> std::ws; // skip whitespaces
    is >> c;
    // should get '+' (imaginary part will follow) or ')' (end)
    if (c == ')') {
        return is;
    } else if (c != '+') {
        is.setstate(std::ios_base::failbit);
        return is;
    }
    // got '+', get imaginary part
    is >> std::ws; // skip whitespaces
    is >> obj.imag();
    // should get 'i'
    is >> std::ws; // skip whitespaces
    is >> c;
    if (c != 'i') {
        is.setstate(std::ios_base::failbit);
        return is;
    }
    // should get closing parenthesis ')'
    is >> std::ws; // skip whitespaces
    is >> c;
    if (c != ')') {
        is.setstate(std::ios_base::failbit);
        return is;
    }
    return is;
}
 
int main()
{
    Complex<> c1(1.0, 2.0);
    Complex<> c2(3.3, -1.5);
 
    Complex<> cpls = c1 + c2;
    //Complex<> cmin = c1 - c2;
    //Complex<> cmlt = c1 * c2;
    //Complex<> cdiv = c1 / c2;
 
    std::cout << c1 << " + " << c2 << " == " << cpls << "\n";
 
    Complex<> c3;
    std::stringstream ssin;
    ssin << "(3.5 +  2.9 i)";
    ssin >> c3;
    std::cout << c3 << "\n";
    return 0;
}

Output:

(1 + 2i) + (3.3 + -1.5i) == (4.3 + 0.5i)
(3.5 + 2.9i)

Functors in C++

Functors are classes with overloaded parenthesis operator operator() which can have any number of arguments.