Object-Oriented Programming In C++: Objects Composition

In real-life, complex objects are often built from smaller, simpler objects. You are built from smaller parts: a head, a body, some legs, arms, etc ... This process of building complex objects from simpler ones is called object composition. Composition is used for objects that have/has a relationship to each other. A house has a door, has a roof, has a balcony. C++ allows us to do object composition in a very simple way by using classes as member variables in other classes. The classes, which those member variables belong to, called suppliers, the host or the client is the class that contains those member variables. For Example: We will write a class maintains employee information as following:
  1. class Employee // maintain employee information
  2. {
  3. private:
  4. // String (ID) and Date are supplier classes
  5. String name; // employee ID (Supplier)
  6. Date birthDate // date of birth (Supplier)
  7. Date hireDate; // date of hire (Supplier)
  8. public:
  9. . . .
  10. };
Notice: - name is an object belongs to String data type (supplier). - birthDate and hireDate are objects belong to Date class (supplier). - Employee class contain name, birthDate and hireDate member variables (host). - We have to define the supplier class before can use it in other classes. So we have to define Date class before defining Employee class:
  1. class Date {
  2. public:
  3. Date( int mn= 1, int dy= 1, int yr = 1900 ) // default constructor
  4. {
  5. if ( mn > 0 && mn <= 12 ) // validate the month
  6. month = mn;
  7. else
  8. {
  9. month = 1;
  10. cout << "Month " << mn << " invalid. Set to month 1.\n";
  11. }
  12. year = yr; // should validate yr
  13. day = checkDay( dy ); // validate the day
  14. cout << "Date object constructor for date ";
  15.  
  16. print(); // interesting: a printwith no arguments
  17. cout << endl;
  18. }
  19. void print() const; // print date in month/day/year format
  20. {
  21. cout << month << '/' << day << '/' << year;
  22. }
  23. ~Date(); // provided to confirm destruction order
  24. {
  25. cout << "Date object destructor for date ";
  26. print();
  27. cout << endl;
  28. }
  29. private:
  30. int month; // 1-12
  31. int day; // 1-31 based on month
  32. int year; // any year
  33.  
  34. // utility function to test proper day for month and year
  35. // based on month and year.
  36. // Is the year 2000 a leap year?
  37. int checkDay( int testDay )
  38. {
  39. static const int daysPerMonth[ 13 ] =
  40. {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  41.  
  42. if ( testDay > 0 && testDay <= daysPerMonth[ month ] )
  43. return testDay;
  44.  
  45. if ( month == 2 && // February: Check for leap year
  46. testDay == 29 &&
  47. ( year % 400 == 0 ||
  48. ( year % 4 == 0 && year % 100 != 0 ) ) )
  49. return testDay;
  50.  
  51. cout << "Day " << testDay << " invalid. Set to day 1.\n";
  52.  
  53. return 1; // leave object in consistent state if bad value
  54. }
  55. };
Now we can define Employee class:
  1. class Employee {
  2. public:
  3. Employee( char *, char *lname,
  4. int bmonth, intbday, int byear,
  5. int hmonth, inthday, int hyear )
  6. : birthDate( bmonth, bday, byear ),
  7. hireDate( hmonth, hday, hyear )
  8. {
  9. // copy fname into firstName andbe sure that it fits
  10. int length = strlen( fname );
  11. length = ( length < 25 ? length : 24 );
  12. strncpy( firstName, fname, length );
  13. firstName[ length ] = '\0';
  14.  
  15. // copy lname into lastName and be sure that it fits
  16. length = strlen( lname );
  17. length = ( length < 25 ? length : 24 );
  18. strncpy( lastName, lname, length );
  19. lastName[ length ] = '\0';
  20.  
  21. cout << "Employee object constructor: "
  22. }
  23. void print() const
  24. {
  25. cout << lastName << ", " << firstName << "\nHired: ";
  26. hireDate.print();
  27. cout << " Birth date: ";
  28. birthDate.print();
  29. cout << endl;
  30. }
  31.  
  32. // Destructor: provided to confirm destruction order
  33. Employee::~Employee()
  34. {
  35. cout << "Employee object destructor: "
  36. << lastName << ", " << firstName << endl;
  37. }
  38. private:
  39. char firstName[ 25 ];
  40. char lastName[ 25 ];
  41. const Date birthDate;
  42. const Date hireDate;
  43. };
Now we can use above classes in Main function:
  1. int main()
  2. {
  3. Employee e( "Bob", "Jones", 7, 24, 1949, 3, 12, 1988 );
  4.  
  5. cout << '\n';
  6. e.print();
  7.  
  8. cout << "\nTest Date constructor with invalid values:\n";
  9. Date d( 14, 35, 1994 ); // invalid Date values
  10. cout << endl;
  11. return 0;
  12. }
The output:
Date object constructor for date 7/24/1949 Date object constructor for date 3/12/1988 Employee object constructor: Bob Jones Jones, Bob Hired: 3/12/1988 Birth date: 7/24/1949 Test Date constructor with invalid values: Month 14 invalid. Set to month 1. Day 35 invalid. Set to day 1. Date object constructor for date 1/1/1994 Date object destructor for date 1/1/1994 Employee object destructor: Jones, Bob Date object destructor for date 3/12/1988 Date object destructor for date 7/24/1949
Note: You can find the full source code of this example in code.zip file.

Tags

Add new comment

CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
3 + 14 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.