Overloading the Assignment Operator:

 < Day Day Up > 



Overloading the Assignment Operator: =

The assignment operator works on two existing objects. Given two Foo objects f1 and f2 the f1 object can be assigned the value of the f2 object in the following manner:

f1 = f2;

To do this the assignment operator need not be overloaded if Foo objects are relatively simple and contain no pointers as data members. The compiler will provide a default assignment operator that will perform a member bitwise copy. To demonstrate this observe the Foo header file shown in example 14.4

Listing 14.4: foo.h

start example
  1  #ifndef _FOO_H  2  #define _FOO_H  3  #include <iostream>  4  using namespace std;  5  6  class Foo{  7      public:  8          Foo(int _i = 0):i(_i){}  9          friend ostream& operator<<(ostream& out, Foo rhs); 10      private: 11          int i; 12  }; 13 14  ostream& operator<<(ostream& out, Foo rhs){ 15      out<<rhs.i<<endl; 16      return out; 17  } 18  #endif
end example

This Foo class contains only one integer data member named i. The constructor has been inlined and the ostream insertion operator overloaded to make inserting Foo objects easier. However, notice that no assignment operator has been declared. Example 14.5 gives a main() function that creates and uses two Foo objects.

Listing 14.5: main.cpp

start example
  1   #include <iostream>  2   using namespace std;    3   #include "foo.h"  4  5   int main(){  6        Foo f1(1), f2(2);  7       cout<<f1<<f2<<endl;  8       f1 = f2;  9       cout<<f1<<f2<<endl; 10        return 0; 11   }
end example

The value of f1 is set to 1 and the value of f2 is set to 2. Their values are printed to the console and then on line 8 the default assignment operator is used to perform a bitwise assignment resulting in f1::i being set to the value of f2::i. Figure 14-3 shows the results of running this program.

click to expand
Figure 14-3: Results of Running Example 14.5

Shallow Copy vs. Deep Copy

The default assignment operator will always perform a bitwise member copy of the right hand side object's data members to the left hand side object's data members. This is also referred to as a shallow copy. If the class contains only simple data members like the Foo class above this is acceptable behavior. However, in the real world of complex objects, a simple shallow copy in not enough.

The danger of performing a shallow copy on complex objects is illustrated in figures 14-4a and 14-4b.

click to expand
Figure 14-4a: Before Shallow Copy of Complex Objects

click to expand
Figure 14-4b: After Shallow Copy of Complex Objects

Figure 14-4a shows two complex objects, A and B, before a shallow copy. Object A contains a pointer that points to some object. Object B, being of the same class, also contains a pointer but it points to a whole different object.

Along comes the shallow copy: A = B; Object B's pointer contents will be assigned to Object A's pointer, meaning Object A's pointer will now point to what Object B's pointer points to. All without deleting Object A's pointer. Memory leak!

When you have a complex class type you must overload the assignment operator to ensure the proper handling of class data members during assignment. To illustrate some of the complexities involved with proper assignment operator overloading I will once again draw your attention to the Person class. In fact, the assignment operator was overloaded for the Person class in chapter 11. You can refer to example 14.1 to see the assignment operator declaration as it appears in the Person class. Example 14.6 gives only the code for the assignment operator as it appears in the person.cpp file.

Listing 14.6: overloaded assignment operator implementation

start example
  1  Person& Person::operator=( Person& rhs ){  2      delete[] f_name;  3     f_name = new char[strlen(rhs.f_name)+1];  4      strcpy(f_name, rhs.f_name);  5  6      delete[] m_name;  7      m_name = new char[strlen(rhs.m_name)+1];  8      strcpy(m_name, rhs.m_name);  9 10      delete[] l_name; 11      l_name = new char[strlen(rhs.l_name)+1]; 12      strcpy(l_name, rhs.l_name); 13 14      name_changed = true; 15 16      return *this; 17  }
end example

The important thing to keep in mind when overloading the assignment operator is that it is working with two existing objects. When the left hand side object has dynamically allocated resources you must do any housekeeping required to ensure those resources are properly treated. In the case of Person class's overloaded assignment operator, it must delete the existing dynamically allocated character arrays and create new ones based on the length of the character arrays of the right hand side object. The characters from the right hand side Person object are then copied into the left hand side Person object's character arrays. You may notice that the Person class's assignment operator only copied the name information. You will have a chance to expand its capabilities in a skill building exercise at the end of the chapter.



 < Day Day Up > 



C++ for Artists. The Art, Philosophy, and Science of Object-Oriented Programming
C++ For Artists: The Art, Philosophy, And Science Of Object-Oriented Programming
ISBN: 1932504028
EAN: 2147483647
Year: 2003
Pages: 340
Authors: Rick Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net