Operator overloading

It is notationally handy to be able to overload the various C++ operators (+, -, =, etc) to have special behaviour when applied to different class objects.

For instance, the + operator is overloaded for the string class so to mean concatenation (i.e. if str1 == "xxx" and str2 == "yyy" then str1 + str2 == "xxxyyy").

Essentially the operator is treated much like a method definition, but using the keyword 'operator' plus the specific symbol (e.g. operator+ for addition, operator- for subtraction, etc.).

The one oddity is that the first operand for the operation is assumed to be the class object itself, e.g. if I had a class named Data, and wanted to be able to add an integer to a Data object (e.g. something like
Data D1; D2 = D1 + 3;) then I would think of D1 as being the object 'calling' the addition operator, 3 as the parameter, and the return value would also be of type Data.

This would give an operator definition something like

class Data {
   public:
      Data  operator(int v);
   ... whatever other stuff ...
};

In the case of our NumericArray class, we might want to overload the + operator to allow us to add a value to every element in the numeric array, e.g.:

class NumericArray {
      // ... all the earlier stuff ... 

      // overloaded assignment operator, allowing us to add
      //    a numeric value to every element in an array
      // e.g. B + 3  would give a copy of B, but with
      //                3 added to each array element
      NumericArray operator+(double right);
};

NumericArray NumericArray::operator+(double right)
{
   if (arr != NULL) {
      for (int i = 0; i < size; i++) {
          arr[i] += right;
      }
   }
   return *this;
} 

Special case: the assignment operators

Whenever a class is defined, the assignment operator (=) is automatically overloaded for that class to simply copy field-by-field.

This is typically the desired behaviour, except when the class in question involves dynamically allocated memory.

Consider a linked list example, if the fields in our linked list class were something like
node *front, *back;
(where node is the struct type for individual list nodes)
Then if we declare two lists, L1 and L2, and try L1 = L2; then this would simply make L1's front and back point to L2's front and back nodes - i.e. they would both be pointing at the same list of nodes in memory.

Since the idea of assignment is more typically to make a copy of the right hand value, this falls short of the desired behaviour. (E.g. if we did a remove from L2 it would also remove the element from L1, since they're both pointing a the same collection of nodes!)

As a result, for classes that involve dynamic memory allocation it is often a good idea to write our own version of the assignment operator(s).

In the NumericArray example we were working with earlier, that might look like:
NumericArray NumericArray::operator=(const NumericArray& src)
{
   if (src.arr == NULL) {
      arr = NULL;
      size = 0;
      return *this;
   } else {
      arr = new double[src.size];
      if (arr == NULL) size = 0;
      else {
         size = src.size;
         for (int i = 0; i < size; i++) {
             arr[i] = src.arr[i];
         }
      }
      return (*this);
   }
}