|
Since every object corresponding to a derived class has residing inside it a subobject corresponding to the base class, it stands to reason that when we copy a derived-class object we would want to ensure that the base-class subobject is also copied in a consistent fashion. This requires that the copy constructor of the base class be called inside the copy constructor of a derived class.
Here is an example that illustrates the point[2]
//DerivedCopyConstruct.cc #include <iostream> using namespace std; class X { // BASE int m; public: //base class constructor: X( int mm ) : m( mm ) {} //base class copy constructor: X( const X& other ) : m( other.m ) {} //(A) void print() { cout << "m of X obj: " << m << endl; } }; class Y : public X { // DERIVED int n; public: //derived class constructor: Y( int mm, int nn ) : X( mm ), n( nn ) {} //derived class copy constructor: Y( const Y& other ) : X( other ), n( other.n ) {} //(B) void print() { X::print(); cout << "n of Y obj: " << n << endl; } }; int main() { X* xptr1 = new X( 5 ); xptr1->print(); // m of X object: 5 cout << endl; Y y1( 2, 3 ); y1.print(); // m of X subobject: 2 // n of Y object: 3 cout << endl; Y y2 = y1; // invokes copy constructor for Y y2.print(); // m of X subobject: 2 // n of Y object: 3 return 0; }
In this example, class Y is derived from X. While the copy constructor of the base class in line (A) above is
X( const X& other ) : m( other.m ) {}
the copy constructor of the derived class in line (B) is
Y( const Y& other ) : X( other ), n( other.n ) {}
Note the invocation of the base-class copy constructor by X( other ) in the copy constructor for the derived class. This invocation causes the X slice of the Y object other to be copied over.
If a derived class has multiple bases, then the copy constructor for the derived class must include proper copying over of the subobjects corresponding to all those bases. Suppose we have
class Y : public X1, public X2 { int n; // };
The copy constructor of this class will, in general, look like
Y( const Y& other ) : X1( other ), X2( other ), n( other.n ) { .... }
The example we showed above really did not need a copy constructor in either the base class or the derived class, since the system-supplied default copy constructor that does byte by byte copying would have sufficed in both cases. You can check that out by commenting out either or both of the copy constructor definitions in lines (A) and (B) of the above program. However, this example illustrates the basic syntax to be followed for incorporating the base-class copy constructor in a derived-class copy constructor.
[2]At this point, the reader may wish to review the copy constructor syntax presented in Chapter 11.
|