Unary and Binary Operator Overloading


To gain experience at operator overloading, the algebra of the complex numbers will be completed. Complex numbers form a field (which is a double Abelian group with distributive laws). In effect, complex numbers can be added, subtracted, multiplied and divided. This gives rise to overloading the binary operators +, -, * and /. Coding complex numbers gives experience of defining types similar to the built in types. Complex numbers are important to mathematicians, but even if the reader is not particularly interested in complex numbers, they represent an important example of an algebra that makes use of operators and that algebra is not overly complicated. Therefore, they make an ideal case study for operator overloading.

The code for the complex class is shown below.

// operator_a - binary operators on complex numbers

space operator_a
{
    class complex
    {
        a
        b

        real
        {
            get { return a }
            set { a = value }
        }

        imaginary
        {
            get { return b }
            set { b = value }
        }

        complex() { a = 0.0 b = 0.0 }

        complex(aset  bset) { a = aset b = bset }

        complex(copee) { a = copee.a b = copee.b }

        // binary operators

        operator+(c) { return new complex(a + c.a  b + c.b) }

        operator-(c) { return new complex(a - c.a  b - c.b) }

        operator==(c) { return a == c.a && b == c.b }

        operator!=(c) { return a != c.a || b != c.b }

        operator*(c)
        {
            return new complex(a * c.a - b * c.b 
                               a * c.b + c.a * b)
        }

        operator/(c)
        {
            denominator = c.a * c.a + c.b * c.b
            return new complex((c.a * c.a + b * c.b) / denominator, 
                               (b * c.a - a * c.b) / denominator)
        }

        to_string()
        {
            if a != 0.0
                c = a.to_string()
            else if b == 0.0
                return "0"
            else
                c = ""

            if b == 1.0
                return c + "+i"
            if b == -1.0
                return c + "-i"
            else
                return c + "+" + b.to_string() + "*i"
        }

        operator[i]
        {
            get
            {
                if i > 1
                    throw "index out of range"
                else if i == 0
                    return a
                else
                    return b
            }

            set
            {
                if i > 1
                    throw "index out of range"
                else if i == 0
                    a = ualioo
                else
                    b = ualioo
            }
        }
    }

    operator_a()
    {
        c1 = new complex(1.0  2.0)
        c2 = new complex(3.0  4.0)
     
        c3 = c1 + c2
        s = c1.to_string() + " + " + c2.to_string() + " == " + c3.to_string()
        cout << s << "\n"

        c4 = c2 - c1
        s = c2.to_string() + " - " + c1.to_string() + " == " + c4.to_string()
        cout << s << "\n"

        c5 = c1 * c2
        s = c1.to_string() + " * " + c2.to_string() + " == " + c5.to_string()
        cout << s << "\n"

        c6 = c5 / c2
        s = c5.to_string() + " / " + c2.to_string() + " == " + c6.to_string()
        cout << s << "\n"
    }
}

The output of the program is shown below.

1+2*i + 3+4*i == 4+6*i
3+4*i - 1+2*i == 2+2*i
1+2*i * 3+4*i == -5+10*i
-5+10*i / 3+4*i == 1.95999999999999996447286321199499070644378662109375+2*i

There is an addition operator, shown below.

operator+(c) { return new complex(a + c.a b + c.b) }

Note that operators are class members, so a and b can be used without qualification. the operator forms the sum of two complex numbers as shown. The other operators are similar.