7.4 Type Conversion and Operator Overloading


Type conversions are often provided to lessen the duplication that frequently occurs when overloading operators. A typical example of this duplication is encountered in defining binary, commutative operators (like +, and *). Suppose that an overloaded set of arithmetic operators is needed in class X so that an int can be added to an object of class X. This requires two operator overloadings: one for the case of "X + int" and one for the case of "int + X". To remove this duplication a type conversion is defined that converts an "int" to an "X" and a single overloading for the case "X + X" is provided. Thus, both "int + X" and "X + int" are converted to the single case "X + X".

An example of manipulating colors will be used to illustrate the use of type conversion and operator overloading. Colors generated by a computer are combination of three primary colors (red, blue, green). Each of the three primary colors has an itensity value associated with it. The range of intensity values determines how many different colors can be produced. If we assume that the intensities are in the range 0-63, then the color "aqua" is generated by using no red and intensities of 50 for both green and blue. To color purple is obtained from aqua by adding red at intensity 63 and adding 13 to the blue intensity.

By using operator overloading it would be desireable to be able to program with colors in the most natural way. The phrasing "add red at intensity nine to aqua" suggests using operator overloading to create a set of arithmetic operators that could be used as follows:


   Color aqua(Red(0), Green(50), Blue(50));

   Color darkRed = Red(63);
   Color purple  = darkRed + aqua + Blue(13);
   Color peach   = purple - Blue(13) - Green(3);

   Color test1 = red + peach;
   Color test2 = peach + red;

   cout << aqua    << endl;
   cout << purple  << endl;
   cout << peach   << endl;
   cout << darkRed << endl;

This usage "reads" naturally. The stream output generated should produce a readable description of the color. For example, outputting the color aqua should result in:
            (red:0, green:50, blue:50)

Ignoring the possibility of type conversions, a first attempt at defining the operator overloading for the Color class might look like the following:

    class Color {
    private:
       Red   red;
       Green green;
       Blue  blue;

    public:
       Color(Red r, Green g, Blue b) 
                  : red(r), green(g), blue(b) {} 

   friend ostream& operator<< (ostream& os, const Color& color);

   friend Color   operator+ (Red   r, Color c);
   friend Color   operator+ (Green g, Color c);
   friend Color   operator+ (Blue  v, Color c);
   friend Color   operator+ (Color c, Red   r);
   friend Color   operator+ (Color c, Green g);
   friend Color   operator+ (Color c, Blue  b);

   friend Color   operator- (Red   r, Color c);
   friend Color   operator- (Green g, Color c);
   friend Color   operator- (Blue  v, Color c);
   friend Color   operator- (Color c, Red   r);
   friend Color   operator- (Color c, Green g);
   friend Color   operator- (Color c, Blue  b);

};

These cases are necessary to account for all the combinations of primary colors (red, green, blue), whether the Color is the right or left hand operand, and whether the operation is addition or subtraction.

A cleaner solution is obtained by using type conversion to elevate a primary color to a general Color before applying the overloaded addition or subtraction operator. This leads to the following design:


    class Color {
    private:
       Red   red;
       Green green;
       Blue  blue;

    public:
       Color(Red r, Green g, Blue b) 
                      : red(r), green(g), blue(b) {} 

       Color(Red   r) : red(r), green(0), blue(0) {}  //convert Red   to Color
       Color(Green g) : red(0), green(g), blue(0) {}  //convert Green to Color
       Color(Blue  b) : red(0), green(0), blue(b) {}  //convert Blue  to Color

       friend ostream& operator<< (ostream& os, const Color& color);

       friend Color   operator+ (Color c1, Color c2);
       friend Color   operator- (Color c1, Color c2);
    };

The three type conversion methods convert each of the primary colors into a general Color objects. Thus,

Last Updated: November 17, 1995 / kafura@cs.vt.edu