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 - unary and binary operators on complex numbers

generic 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(copy) { a = copy.a b = copy.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"
        els
            c = ""

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

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

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

generic operator_a
{
    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()
        s.println()

        c4 = c2 - c1
        s = c2.to_string() + " - " + c1.to_string() + " == " + c4.to_string()
        s.println()

        c5 = c1 * c2
        s = c1.to_string() + " * " + c2.to_string() + " == " + c5.to_string()
        s.println()

        c6 = c5 / c2
        s = c5.to_string() + " / " + c2.to_string() + " == " + c6.to_string()
        s.println()
    }
}

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.