Operator overloading in C++


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 output stream and a reference to object to write, it returns as well a reference to the output stream.

Run this code
#include #include 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(ComplexT> const& other) = default; /// destructor virtual ~Complex() = default; // assignment operator, generated by compiler ComplexT>& operator=(ComplexT> const& other) = default; // addition ComplexT> operator+(ComplexT> const& rhs) const; // this could be a template method with any Complex convertible to Complex ComplexT>& operator+=(ComplexT> const& rhs); // subtraction ComplexT> operator-(ComplexT> const& rhs) const; ComplexT>& operator-=(ComplexT> const& rhs); // multiplication ComplexT> operator*(ComplexT> const& rhs) const; ComplexT>& operator*=(ComplexT> const& rhs); // division ComplexT> operator/(ComplexT> const& rhs) const; ComplexT>& operator/=(ComplexT> const& rhs); private: value_type m_real; value_type m_imag; }; template typename T> ComplexT> ComplexT>::operator+(ComplexT> const& rhs) const { ComplexT> result = *this; result += rhs; return result; } template typename T> ComplexT>& ComplexT>::operator+=(ComplexT> const& rhs) { m_real += rhs.m_real; m_imag += rhs.m_imag; return *this; } template typename T> std::ostream& operator<(std::ostream& os, ComplexT> const& obj) { // output (real_part + imaginary_part"i") os  <"("  real()  <" + "  imag()  <"i)"; return os; } template typename T> std::istream& operator>>(std::istream& is, ComplexT>& 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   <" + "   <" == "   <"\n"; Complex<> c3; std::stringstream ssin; ssin  <"(3.5 + 2.9 i)"; ssin >> c3; std::cout   <"\n"; return 0; }
(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.

This section is incomplete