9.11. Composition: Objects as Members of Classes

An AlarmClock object needs to know when it’s supposed to sound its alarm, so why not include a Time object as a member of the AlarmClock class? Such a capability is called composition and is sometimes referred to as a has-a relationshipa class can have objects of other classes as members.


Image Software Engineering Observation 9.9

A common form of software reusability is composition, in which a class has objects of other types as members.


Previously, we saw how to pass arguments to the constructor of an object we created in main. Now we show how an class’s constructor can pass arguments to member-object constructors via member initializers.


Image Software Engineering Observation 9.10

Data members are constructed in the order in which they’re declared in the class definition (not in the order they’re listed in the constructor’s member initializer list) and before their enclosing class objects (sometimes called host objects) are constructed.


The next program uses classes Date (Figs. 9.179.18) and Employee (Figs. 9.199.20) to demonstrate composition. Class Employee’s definition (Fig. 9.19) contains private data members firstName, lastName, birthDate and hireDate. Members birthDate and hireDate are const objects of class Date, which contains private data members month, day and year. The Employee constructor’s header (Fig. 9.20, lines 10–11) specifies that the constructor has four parameters (first, last, dateOfBirth and dateOfHire). The first two parameters are passed via member initializers to the string class constructor for the firstName and lastName data members. The last two are passed via member initializers to the Date class constructor for the birthDate and hireDate data members.


 1   // Fig. 9.17: Date.h
 2   // Date class definition; Member functions defined in Date.cpp
 3   #ifndef DATE_H
 4   #define DATE_H
 5
 6   class Date
 7   {
 8   public:
 9      static const unsigned int monthsPerYear = 12; // months in a year
10      explicit Date( int = 1, int = 1, int = 1900 ); // default constructor
11      void print() const; // print date in month/day/year format
12      ~Date(); // provided to confirm destruction order
13   private:
14      unsigned int month; // 1-12 (January-December)
15      unsigned int day; // 1-31 based on month
16      unsigned int year; // any year
17
18      // utility function to check if day is proper for month and year
19      unsigned int checkDay( int ) const;
20   }; // end class Date
21
22   #endif


Fig. 9.17. Date class definition.


 1   // Fig. 9.18: Date.cpp
 2   // Date class member-function definitions.
 3   #include <array>
 4   #include <iostream>
 5   #include <stdexcept>
 6   #include "Date.h" // include Date class definition
 7   using namespace std;
 8
 9   // constructor confirms proper value for month; calls
10   // utility function checkDay to confirm proper value for day
11   Date::Date( int mn, int dy, int yr )
12   {
13      if ( mn > 0 && mn <= monthsPerYear ) // validate the month
14         month = mn;
15      else
16         throw invalid_argument( "month must be 1-12" );
17
18      year = yr; // could validate yr
19      day = checkDay( dy ); // validate the day
20
21      // output Date object to show when its constructor is called
22      cout << "Date object constructor for date ";
23      print();
24      cout << endl;
25   } // end Date constructor
26
27   // print Date object in form month/day/year
28   void Date::print() const
29   {
30      cout << month << '/' << day << '/' << year;
31   } // end function print
32
33   // output Date object to show when its destructor is called
34   Date::~Date()
35   {
36      cout << "Date object destructor for date ";
37      print();
38      cout << endl;
39   } // end ~Date destructor
40
41   // utility function to confirm proper day value based on
42   // month and year; handles leap years, too
43   unsigned int Date::checkDay( int testDay ) const
44   {
45      static const array< int, monthsPerYear + 1 > daysPerMonth =
46         { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
47
48      // determine whether testDay is valid for specified month
49      if ( testDay > 0 && testDay <= daysPerMonth[ month ] )
50         return testDay;
51
52      // February 29 check for leap year
53      if ( month == 2 && testDay == 29 && ( year % 400 == 0 ||
54         ( year % 4 == 0 && year % 100 != 0 ) ) )
55         return testDay;
56
57      throw invalid_argument( "Invalid day for current month and year" );
58   } // end function checkDay


Fig. 9.18. Date class member-function definitions.


 1   // Fig. 9.19: Employee.h
 2   // Employee class definition showing composition.
 3   // Member functions defined in Employee.cpp.
 4   #ifndef EMPLOYEE_H
 5   #define EMPLOYEE_H
 6
 7   #include <string>
 8   #include "Date.h" // include Date class definition
 9
10   class Employee
11   {
12   public:
13      Employee( const std::string &, const std::string &,
14         const Date &, const Date & );
15      void print() const;
16      ~Employee(); // provided to confirm destruction order
17   private:
18      std::string firstName; // composition: member object
19      std::string lastName; // composition: member object
20      const Date birthDate; // composition: member object
21      const Date hireDate; // composition: member object
22   }; // end class Employee
23
24   #endif


Fig. 9.19. Employee class definition showing composition.


 1   // Fig. 9.20: Employee.cpp
 2   // Employee class member-function definitions.
 3   #include <iostream>
 4   #include "Employee.h" // Employee class definition
 5   #include "Date.h" // Date class definition
 6   using namespace std;
 7
 8   // constructor uses member initializer list to pass initializer
 9   // values to constructors of member objects
10   Employee::Employee( const string &first, const string &last,
11      const Date &dateOfBirth, const Date &dateOfHire )
12      : firstName( first ), // initialize firstName      
13        lastName( last ), // initialize lastName         
14        birthDate( dateOfBirth ), // initialize birthDate
15        hireDate( dateOfHire ) // initialize hireDate    
16   {
17      // output Employee object to show when constructor is called
18      cout << "Employee object constructor: "
19         << firstName << ' ' << lastName << endl;
20   } // end Employee constructor
21
22   // print Employee object
23   void Employee::print() const
24   {
25      cout << lastName << ", " << firstName << "  Hired: ";
26      hireDate.print();
27      cout << "  Birthday: ";
28      birthDate.print();
29      cout << endl;
30   } // end function print
31
32   // output Employee object to show when its destructor is called
33   Employee::~Employee()
34   {
35      cout << "Employee object destructor: "
36         << lastName << ", " << firstName << endl;
37   } // end ~Employee destructor


Fig. 9.20. Employee class member-function definitions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.140.111