////////////////////////////////////////////////////////////////// // DEM_AGG2.CPP -- demonstrates aggregation // // knows how to copy, assign, and destroy // // uses inefficient copy ctor design // ////////////////////////////////////////////////////////////////// #include class base { public: base(void); base(const base& b); base(int x); virtual ~base(void); base& operator= (const base& b); friend ostream& operator<<(ostream& ostrm, const base& b); private: int data; }; class aggr { public: aggr(void); aggr(const aggr &a); aggr(int x1, int x2); virtual ~aggr(void); aggr& operator=(const aggr& a); friend ostream& operator<<(ostream& ostrm, const aggr& a); private: base b1; base b2; }; // //----< void constructor >------------------------------------- base::base(void) { cout << " base void constructor called\n"; } //----< copy constructor >------------------------------------- base::base(const base& b) : data(b.data) { cout << " base copy constructor called\n"; } //----< promotion constructor >-------------------------------- base::base(int x) : data(x) { cout << " base(int) constructor called\n"; cout << " set data = " << data << "\n"; } //----< destructor >------------------------------------------- base::~base(void) { cout << " base destructor called\n"; } //----< assignment >------------------------------------------- base& base::operator= (const base& b) { cout << " base operator= called\n"; data = b.data; return *this; } //----< insertion >-------------------------------------------- ostream& operator<<(ostream& ostrm, const base& b) { ostrm << b.data; return ostrm; } // //----< void constructor >------------------------------------- aggr::aggr(void) { cout << " aggr void constructor called\n"; } //----< copy constructor >------------------------------------- // this assignment method is not efficient - see dem_ag2b aggr::aggr(const aggr &a) { cout << " aggr copy constructor called\n"; b1 = a.b1; b2 = a.b2; } //----< promotion constructor with initialization >------------ aggr::aggr(int size1, int size2) : b1(size1), b2(size2) { cout << " aggr(int,int) constructor called\n"; cout << " set b1 = " << b1 << endl; cout << " set b2 = " << b2 << endl; } //----< destructor >------------------------------------------- aggr::~aggr(void) { cout << " aggr destructor called\n"; } //----< assignment >------------------------------------------- aggr& aggr::operator=(const aggr &a) { cout << " aggr operator= called\n"; b1 = a.b1; b2 = a.b2; return *this; } //----< annunciator >------------------------------------------ void message(char *s) { cout << endl << s << " executable statement of main\n"; } void main() { //---------------------------------------------- message("1st"); base b1; message("2nd"); base b2 = b1; message("3rd"); b1 = b2; message("4th"); aggr a1; message("5th"); aggr a2(6,4); message("6th"); aggr a3 = a1; message("7th"); a3 = a2; message("no more"); } // // now, agger has a copy ctor, assignment oper, and a dtor // - we see them being called in 6th statement, 7th // statement, and in the destruction sequence // one issue of note here: // if you compare aggr source code for copy ctor and // annunciations you will see that when aggr does a copy // construction it's elements are first constructed with // void ctor, then assigned with base operator=() // there is a better way - see dem_ag2b