10.8. Case Study: A Date Class

The program of Figs. 10.610.8 demonstrates a Date class, which uses overloaded prefix and postfix increment operators to add 1 to the day in a Date object, while causing appropriate increments to the month and year if necessary. The Date header (Fig. 10.6) specifies that Date’s public interface includes an overloaded stream insertion operator (line 11), a default constructor (line 13), a setDate function (line 14), an overloaded prefix increment operator (line 15), an overloaded postfix increment operator (line 16), an overloaded += addition assignment operator (line 17), a function to test for leap years (line 18) and a function to determine whether a day is the last day of the month (line 19).


 1   // Fig. 10.6: Date.h
 2   // Date class definition with overloaded increment operators.
 3   #ifndef DATE_H
 4   #define DATE_H
 5
 6   #include <array>
 7   #include <iostream>
 8
 9   class Date
10   {
11      friend std::ostream &operator<<( std::ostream &, const Date & );
12   public:
13      Date( int m = 1, int d = 1, int y = 1900 ); // default constructor
14      void setDate( int, int, int ); // set month, day, year
15      Date &operator++(); // prefix increment operator                  
16      Date operator++( int ); // postfix increment operator             
17      Date &operator+=( unsigned int ); // add days, modify object      
18      static bool leapYear( int ); // is date in a leap year?
19      bool endOfMonth( int ) const; // is date at the end of month?
20   private:
21      unsigned int month;
22      unsigned int day;
23      unsigned int year;
24
25      static const std::array< unsigned int, 13 > days; // days per month
26      void helpIncrement(); // utility function for incrementing date
27   }; // end class Date
28
29   #endif


Fig. 10.6. Date class definition with overloaded increment operators.


 1   // Fig. 10.7: Date.cpp
 2   // Date class member- and friend-function definitions.
 3   #include <iostream>
 4   #include <string>
 5   #include "Date.h"
 6   using namespace std;
 7
 8   // initialize static member; one classwide copy
 9   const array< unsigned int, 13 > Date::days =
10      { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
11
12   // Date constructor
13   Date::Date( int month, int day, int year )
14   {
15      setDate( month, day, year );
16   } // end Date constructor
17
18   // set month, day and year
19   void Date::setDate( int mm, int dd, int yy )
20   {
21      if ( mm >= 1 && mm <= 12 )
22         month = mm;
23      else
24         throw invalid_argument( "Month must be 1-12" );
25
26      if ( yy >= 1900 && yy <= 2100 )
27         year = yy;
28      else
29         throw invalid_argument( "Year must be >= 1900 and <= 2100" );
30
31      // test for a leap year
32      if ( ( month == 2 && leapYear( year ) && dd >= 1 && dd <= 29 ) ||
33           ( dd >= 1 && dd <= days[ month ] ) )
34         day = dd;
35      else
36         throw invalid_argument(
37            "Day is out of range for current month and year" );
38   } // end function setDate
39
40   // overloaded prefix increment operator                 
41   Date &Date::operator++()                                
42   {                                                       
43      helpIncrement(); // increment date                   
44      return *this; // reference return to create an lvalue
45   } // end function operator++                            
46
47   // overloaded postfix increment operator; note that the  
48   // dummy integer parameter does not have a parameter name
49   Date Date::operator++( int )                             
50   {                                                        
51      Date temp = *this; // hold current state of object    
52      helpIncrement();                                      
53                                                            
54      // return unincremented, saved, temporary object      
55      return temp; // value return; not a reference return  
56   } // end function operator++                             
57
58   // add specified number of days to date                    
59   Date &Date::operator+=( unsigned int additionalDays )      
60   {                                                          
61      for ( int i = 0; i < additionalDays; ++i )              
62         helpIncrement();                                     
63                                                              
64      return *this; // enables cascading                      
65   } // end function operator+=                               
66
67   // if the year is a leap year, return true; otherwise, return false
68   bool Date::leapYear( int testYear )
69   {
70      if ( testYear % 400 == 0 ||
71         ( testYear % 100 != 0 && testYear % 4 == 0 ) )
72         return true; // a leap year
73      else
74         return false; // not a leap year
75   } // end function leapYear
76
77   // determine whether the day is the last day of the month
78   bool Date::endOfMonth( int testDay ) const
79   {
80      if ( month == 2 && leapYear( year ) )
81         return testDay == 29; // last day of Feb. in leap year
82      else
83         return testDay == days[ month ];
84   } // end function endOfMonth
85
86   // function to help increment the date
87   void Date::helpIncrement()
88   {
89      // day is not end of month
90      if ( !endOfMonth( day ) )
91         ++day; // increment day
92      else
93         if ( month < 12 ) // day is end of month and month < 12
94         {
95            ++month; // increment month
96            day = 1; // first day of new month
97         } // end if
98         else // last day of year
99         {
100           ++year; // increment year
101           month = 1; // first month of new year
102           day = 1; // first day of new month
103        } // end else
104  } // end function helpIncrement
105
106  // overloaded output operator
107  ostream &operator<<( ostream &output, const Date &d )
108  {
109     static string monthName[ 13 ] = { "", "January", "February",
110        "March", "April", "May", "June", "July", "August",
111        "September", "October", "November", "December" };
112     output << monthName[ d.month ] << ' ' << d.day << ", " << d.year;
113     return output; // enables cascading
114  } // end function operator<<


Fig. 10.7. Date class member- and friend-function definitions.


 1   // Fig. 10.8: fig10_08.cpp
 2   // Date class test program.
 3   #include <iostream>
 4   #include "Date.h" // Date class definition
 5   using namespace std;
 6
 7   int main()
 8   {
 9      Date d1( 12, 27, 2010 ); // December 27, 2010
10      Date d2; // defaults to January 1, 1900
11
12      cout << "d1 is " << d1 << " d2 is " << d2;
13      cout << " d1 += 7 is " << ( d1 += 7 );
14
15      d2.setDate( 2, 28, 2008 );
16      cout << "   d2 is " << d2;
17      cout << " ++d2 is " << ++d2 << " (leap year allows 29th)";
18
19      Date d3( 7, 13, 2010 );
20
21      cout << " Testing the prefix increment operator: "
22         << " d3 is " << d3 << endl;                        
23      cout << "++d3 is " << ++d3 << endl;                   
24      cout << " d3 is " << d3;                              
25
26      cout << " Testing the postfix increment operator: "
27         << " d3 is " << d3 << endl;                         
28      cout << "d3++ is " << d3++ << endl;                    
29      cout << " d3 is " << d3 << endl;                       
30   } // end main


d1 is December 27, 2010
d2 is January 1, 1900

d1 += 7 is January 3, 2011

  d2 is February 28, 2008
++d2 is February 29, 2008 (leap year allows 29th)

Testing the prefix increment operator:
  d3 is July 13, 2010
++d3 is July 14, 2010
  d3 is July 14, 2010

Testing the postfix increment operator:
  d3 is July 14, 2010
d3++ is July 14, 2010
  d3 is July 15, 2010


Fig. 10.8. Date class test program.

Function main (Fig. 10.8) creates two Date objects (lines 9–10)—d1 is initialized to December 27, 2010 and d2 is initialized by default to January 1, 1900. The Date constructor (defined in Fig. 10.7, lines 13–16) calls setDate (defined in Fig. 10.7, lines 19–38) to validate the month, day and year specified. Invalid values for the month, day or year result in invalid_argument exceptions.

Line 12 of main (Fig. 10.8) outputs each of the Date objects, using the overloaded stream insertion operator (defined in Fig. 10.7, lines 107–114). Line 13 of main uses the overloaded operator += (defined in Fig. 10.7, lines 59–65) to add seven days to d1. Line 15 in Fig. 10.8 uses function setDate to set d2 to February 28, 2008, which is a leap year. Then, line 17 preincrements d2 to show that the date increments properly to February 29. Next, line 19 creates a Date object, d3, which is initialized with the date July 13, 2010. Then line 23 increments d3 by 1 with the overloaded prefix increment operator. Lines 21–24 output d3 before and after the preincrement operation to confirm that it worked correctly. Finally, line 28 increments d3 with the overloaded postfix increment operator. Lines 26–29 output d3 before and after the postincrement operation to confirm that it worked correctly.

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

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