(Latest Revision:
Wed Apr 2 23:34:56 PST 2003
)
ch08_Notes04_Overloads
ch08 Notes on Overloads
Polymorphism: the meaning of a function or operator
can vary according to the number of parameters, or the data types
of the parameters, or the the invoking object .
Simple example(s):
- "5 + 4" and "5.0 + 4.0" really
operate quite differently. The operator takes a
different form depending on the data types of the operands. If
s and t are strings, s+t may mean
the result of appending t to s.
If you define a new class, operators like "==" won't
be supplied by the compiler. A "shallow" form of the operator "="
will be furnished, but you may have to
redefine "=" to get a deep copy.
For example, to provide a definition for "==" that works for your
new list class, you can put code like this inside the class
definition in the header file for the class (e.g. listClass.h):
virtual bool operator==(const listClass & Rhs) const ;
The items in boldface are keywords.
Inside the implementation file (say listClass.cpp) you put code
like this:
bool listClass::operator==(const listClass& Rhs) const
{
bool IsEqual;
if (Size != Rhs.Size)
IsEqual = false; // lists have unequal lengths
else if ( (Head == NULL) && (Rhs.Head == NULL) )
IsEqual = true; // both lists are empty
else // lists have same length > 0;
// head pointers not NULL
{ // compare items
ptrType LeftPtr = Head;
ptrType RightPtr = Rhs.Head;
for (int Count = 1;
(Count <= Size) &&
(LeftPtr->Item == RightPtr->Item);
++Count)
{ LeftPtr = LeftPtr->Next;
RightPtr = RightPtr->Next;
} // end for
IsEqual = Count > Size;
} // end if
return IsEqual;
} // end operator==
Assuming that "==" 'makes sense' for comparing list items, the code above
states in essence that two lists are equal if they
have the same length and their corresponding elements are equal.
After putting the definitions illustrated above in
place, we may make comparisions like "X==Y" where X and Y are
objects of the list class. When we write such code, the compiler interprets it as a call to the operator==
defined as we showed. Y plays the role of the Rhs
parameter (right hand side of the operator). X plays the role of the object that receives the message.
The programmer may overload these operators too: {
<, <=, >, >= }.
Also it is typically necessary to overload "=" when a class
contains a pointer to a dynamically allocated structure. We do
this to get a "deep copy" instead of a "shallow copy."
There are some subtleties:
- To get things like L = M = N to work right, you need to make "=" return a reference to the
invoking object.
- You need to avoid a "memory leak" in the implementation of "=".
In particular when some dynamically allocated structure is about
to be replaced, the code must first
deallocate the old structure.
- You have to write the code so that a
call like L = L will not do the wrong thing.
GUIDELINES:
- You can overload any C++ operator except { ., .*, ::,
?:, sizeof)
- You cannot define new operators by overloading symbols
that are not already operators in C++.
- You cannot change the standard precedence of a C++
operator or the number of its operands.
- At least one operand of an overloaded operator must be
an instance of a class.
- A typical class should overload at least
the assignment (=), the equality (== and !=), and the relational
(<, <=, >, >=) operators (if the relational operators
'make sense').