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->real,
imag + c->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->real;
imag = c->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:
- Assign animation instrumentation to the project by selecting .
- Make and run
DefaultConfig.exe
. - Using the animator, create an animated sequence
diagram (ASD) that includes the
MainClass
and instancesComplex[0]:Complex
,Complex[1]:Complex
, andComplex[2]:Complex
. - 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.