Overloading operators

You can overload operators for classes created in Rhapsody® . For example, for a Stack class, you can overload the "+" operator to automatically perform a push() operation, and the "‑" operator to automatically perform a pop() operation.

About this task

All the overloaded operators (such as operator+ and operator-) can be modeled as member functions, except for the stream output operator<<, which is a global function rather than a member function and must be declared a friend function. The overloaded operators that are class members are all defined as primitive operations.

To illustrate operator overloading, consider two classes, Complex and MainClass, defined as follows:

Complex Class

About this task

Attributes:
   double imag;
   double real;
Operations:
   Complex()                  // Simple constructor   Body:
   {
      real = imag = 0.0;
   }
   Complex(const Complex& c)  //Copy constructor   Arguments: const Complex& c
   Body:
   {
      real = c.real;
      imag = c.imag;
   }
   Complex(double r, double i) // Convert constructor   Arguments:  double r
               double i = 0.0
   Body: 
   {
      real = r;
      imag = i;
   }

   operator-(Complex c)        // Subtraction   Return type: Complex
   Arguments: Complex c
   Body: 
   {
      return Complex(real - c.real, imag - c.imag);
   }
   operator[](int index)      // Array subscript   Return type: Complex&
   Arguments: int index       // dummy operator - only 
                              // for instrumentation
                              // check
   Body: 
   {
      return *this;
   }
   operator+(Complex& c)      // Addition by value   Return type: Complex
   
   Arguments: Complex& c
   Body: 
   {
      return Complex(real + c.real,imag + c.imag);
   }
   operator+(Complex* c)      // Addition by reference   Return type: Complex*
   Arguments: Complex *c
   Body: 
   {
      cGlobal = new Complex (real + c-&gt;real, 
         imag + c-&gt;imag);
      return cGlobal;
   }
   operator++()               // Prefix increment   Return type: Complex&
   Body: 
   {
      real += 1.0;
      imag += 1.0;
      return *this;
   }
   operator=(Complex& c)      // Assignment by value   Return type: Complex&
   Arguments: Complex& c
   Body: 
   {
      real = c.real,
      imag = c.imag;
      return *this;
   }



   operator=(Complex* c)      // Assignment by reference   Return type: Complex*
   Arguments: Complex *c
   Body: 
   {
      real = c-&gt;real;
      imag = c-&gt;imag;
      return this;
   }

The following are some examples of code generated for these overloaded operators.

This is the code generated for the overloaded prefix increment operator:

Complex& Complex::operator++() {
   NOTIFY_OPERATION(operator++, operator++(), 0,
      operator_SERIALIZE);
   //#[ operation operator++()
   real += 1.0;
   imag += 1.0;
   return *this;
   //#]
};

This is the code generated for the overloaded + operator:

Complex Complex::operator+(Complex&  c) {
   NOTIFY_OPERATION(operator+, operator+(Complex&), 1,
      OM_operator_1_SERIALIZE);
   //#[ operation operator+(Complex&)
   return Complex(real + c.real, imag + c.imag);
   //#]
};

This is the code generated for the first overloaded assignment operator:

Complex& Complex::operator=(Complex&  c) {
   NOTIFY_OPERATION(operator=, operator=(Complex&), 1,
      OM_operator_2_SERIALIZE);
   //#[ operation operator=(Complex&)
   real = c.real;
   imag = c.imag;
   return *this;
//#]
};

The browser lists the MainClass, which is a composite that instantiates three Complex classes.

Its attributes are as follows:

Complex* c1
Complex* c2
Complex* c3
Body~MainClass()         //DestructorBody 
{
   delete c1;
   delete c2;
   delete c3;
}
e()                  // Event

The stream output operator << is a global function that must be declared a friend to classes that want to use it. It is defined as follows:

operator<<
Return type: ostream&
Arguments:   ostream& s
            Complex& c
Body: 
{
   s << "real part = " "<< c.real<< 
      "imagine part = " << c.imag << "\n" << flush;
   return s;
}

To watch the various constructors and overloaded operators as they are being called:

  1. Assign animation instrumentation to the project by selecting Code > Set Configuration > Edit > Setting tab.
  2. Make and run DefaultConfig.exe.
  3. Using the animator, create an animated sequence diagram (ASD) that includes the MainClass and instances Complex[0]:Complex, Complex[1]:Complex, and Complex[2]:Complex.
  4. Click Go on the Animation bar to watch the constructor and overloaded operator messages being passed between the MainClass and its part instances.

    The animated sequence diagram will be similar to the following figure.