|
As was the case for the copy constructor of a derived class, the assignment operator of a derived class must also invoke the assignment operator of the base class. Including the assignment operators in the definitions of the base class X and the derived class Y of the previous example, we get[3]
//DerivedAssignOp.cc #include <iostream> using namespace std; class X { // BASE int m; public: //constructor: X( int mm ) : m( mm ) {} //copy constructor: X( const X& other ) : m( other.m ) {} //assignment op: X& operator=( const X& other ) { //(A) if ( this == &other ) return *this; m = other.m; return *this; } void print() { cout << "m of X obj: " << m << endl; } }; class Y : public X { // DERIVED int n; public: //constructor: Y( int mm, int nn ) : X( mm ), n( nn ) {} //copy constructor: Y( const Y& other ) : X( other ), n( other.n ) {} //assignment op: Y& operator=( const Y& other ) { //(B) if ( this == &other ) return *this; X::operator=( other ); n = other.n; return *this; } void print() { X::print(); cout << "n of Y obj: " << n << endl; } }; int main() { X xobj_1( 5 ); // X's constructor X xobj_2 = xobj_1; //X's copy constructor X xobj_3( 10 ); xobj_3 = xobj_2; // X's assignment op xobj_3.print(); // m of X obj: 5 cout << endl; Y yobj_1( 100, 110 ); // Y's constructor Y yobj_2 = yobj_1; // Y's copy constructor Y yobj_3( 200, 220 ); yobj_3 = yobj_2; // Y's assignment op yobj_3.print(); // m of X obj: 100 // n of Y obj: 110 cout << endl; }
The assignment operator for the base class is defined as follows in line (A) above:
X& operator=( const X& other ) { if ( this == &other ) return *this; m = other.m; return *this; }
And the assignment operator for the derived class is defined in line (B) above by
Y& operator=( const Y& other ) { if ( this == &other ) return *this; X::operator=( other ); //(C) n = other.n; return *this; }
Note the invocation in line (C):
X::operator=( other );
This applies the base-class assignment operator to the base-class slice of the derived-class object.
These constructs for the assignment operation can be generalized to the case of a derived class inheriting from multiple bases. Suppose, we have
class Y : public X1, public X2 { int n; // };
The assignment operator for this class will look like
Y& operator=( const Y& other ) { if ( this == &other ) return *this; X1::operator=( other ); //(D) X2::operator=( other ); //(E) n = other.n; return *this; }
Note how the subobjects corresponding to the two bases are assigned over in lines (D) and (E).
It is important to note that the classes X and Y in the above program really do not need programmer-defined assignment operators, since the system-supplied default meaning of the assignment operator would suffice for these simple classes. You can check that out by commenting out either or both of the definitions of the copy assignment operators in lines (A) and (B) of the program. However, the example does illustrate the basic syntax to be used when incorporating the assignment operator of the base class in the assignment operator of a derived class.
[3]Before looking at this example code, the reader may wish to review the material on copy assignment operators in Chapter 11.
|