当前位置: 首页 > 文档资料 > C++大学教程 >

8.12 实例研究:Date 类

优质
小牛编辑
112浏览
2023-12-01

图 8.6 声明了类 Date。类 Date 用重载的前置和后置自增运算符将一个 Date 对象增加1天,必要时使年、月递增。

类 Date 的 Public 接口提供了以下成员函数:一个重载的流插入运算符,一个默认的构造函数、一个 setDate 函数、一个重载的前置自增运算符函数、一个重载的后置自增运算符函数、一个重载的加法赋值运算符(+=)、一个检测闰年的函数和一个判断是否为每月最后一天的函数。

1 // Fig. 8.6: datel.h
2 // Definition of class Date
3 #ifndef DATE1_H
4 #define DATE1_H
5 #include <iostream.h>
6
7 class Date {
8 friend ostream &operator<<( ostream &, const Date & );
9
10 public:
11 Date( int m = 1, int d = 1, int y = 1900 ); // Constructor
12 void setDate( int, int, int ); // set the date
13 Date &operator++(); // preincrement operator
14 Date operator++( int ); // postincrement operator
15 const Date &operator+=( int ); // add days,modify object
16 bool leapYear( int ); // is this a leap year?
17 bool endOfMonth( int ); // is this end of month?
18
19 private:
20 int month;
21 int day;
22 int year;
23
24 static const int days[]; // array of days per month
25 void helpIncrement(); // utility function
26 };
27
28 #endif
30 // Member function definitions for Date class
31 #include <iostream.h>
32 #include "date1.h"
33
34 // Initialize static member at file scope;
35 // one class-wide copy.
36 const int Date::days[] = { 0, 31, 28, 31, 30, 31,30,
37 31, 31, 30, 31, 30, 31 } ;
38
39 // Date constructor
40 Date::Date( int m, int d, int y ) { setDate( m, d, y ); }
41
42 // Set the date
43 void Date::setDate{ int mm, int dd, int yy )
44 {
45 month = ( mm >= 1 && mm <= 12 ) ? mm : 1;
46 year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900;
47
48 // test for a leap year
49 if ( month == 2 && leapYear( year ) )
50 day = ( dd >= 1 && dd <= 29 ) ? dd : 1;
51 else
52 day = ( dd >= 1 && dd <= days[ month ] ) ? dd : 1;
53 }
54
55 // Preincrement operator overloaded as a member function.
56 Date &Date::operator++()
57 {
58 helpIncrement();
59 return *this; // reference return to create an lvalue
6O }
61
62 // Postincrement operator overloaded as a member function.
63 // Note that the dummy integer parameter does net have a
65 Date Date::operator++( int)
66 {
67 Date temp = *this;
68 helpIncrement();
69
70 // return non-incremented, saved, temporary object
71 return temp; // value return; not a reference return
72 }
73
74 // Add a specific number of days to a date
75 const Date &Date::operator+=( int additionalDays )
76 {
77 for ( int i = 0; i < additionalDays; i++ )
78 helpIncrement();
79
80 return *this; // enables cascading
81 }
82
83 // If the year is a leap year, return true;
84 // otherwise,return false
85 bool Date::leapYear( int y )
86 {
87 if ( y % 400 == 0 || ( y % 100 != 0 && y % 4 == 0 ) )
88 return true; // a leap year
89 else
90 return false; // not a leap year
91 }
92
93 // Determine if the day is the end of the month
94 bool Date::endOfMonth( int d )
95 {
96 if ( month == 2 && leapYear( year ) )
97 return d == 29; // last day of Feb. in leap year
98 else
99 return d == days[ month ];
100 }
101
102 // Function to help increment the date
103 void Date::helpIncrement()
104 {
105 if ( endOfMonth( day ) && month == 12 ) { // end year
106 day = 1;
107 month = 1;
108 ++year;
109 }
110 else if ( endOfMonth( day ) ) { // end
111 day = 1;
112 ++month;
113 }
114 else // not end of month or year; increment day
115 ++day;
116 }
117
118 // Overloaded output operator
119 ostream &operator<<( ostream &output, const Date &d )
120 {
121 static char *monthName[ 13 ] = { "", "January",
122 "February", "March", "April", "May", "June",
123 "July", "August", "September", "October",
124 "November", "December"} ;
125
126 output << monthName[ d.month ] << ' '
127 << d.day << ", "<< d.year;
128
129 return output; // enables cascading
130 }
131 // Fig. 8.6: fig08_06.cpp
132 // Driver for class Date
133 #include <iostream.h>
134 #include "date1.h"
135
136 int main()
137 {
138 Date d1, d2( 12, 27, 1992 ), d3( 0, 99, 8045 );
139 cout << "d1 is "<< d1
140 << "\nd2 is" << d2
141 << "\nd3 is << d3 << "\n\n";
142
143 cout << "d2 + 7 is "<< ( d2 += 7 ) << "\n\n";
144
145 d3.setDate( 2, 28, 1992 );
146 cout <<" d3 is "<< d3;
147 cout << "\n++d3 is" << ++d3 << "\n\n";
148
149 Date d4( 3, 18, 1969 );
150
151 cout << "Testing the preincrement operator:\n"
152 <<" d4 is" << d4 << '\n';
153 cout << "++d4 is "<< ++d4 << '\n';
154 cout <<" d4 is << d4 << "\n\n";
155
156 cout << "Testing the postincrement operator:\n"
157 <<" d4 is "<< d4 << '\n';
158 cout << "d4++ is " << d4++ << '\n';
159 cout << "d4 is " << << d4 << endl;
160
161 return O;
162 }

输出结果:

dl is January 1, 1900
d2 is December 27, 1992
d3 is January 1,1900

d2 += 7 is January 3,1993

d3 is February 28, 1992
++d3 is February 29, 1992

Testing the preincrement operator:
d4 is March 18,1969
++d4 is March 19, 1969
d4 is March 19, 1969

Testing the preincrement operator:
d4 is March 19, 1969
d4++ is March 19, 1969
d4 is March 20, 1969

图 8.6 重载自增运算符的 Date 类

main 函数中的驱动程序建立了几个日期对象,包括:初始化为1990年1月1日的d1,初始化为1992年12月27日的d2以及初始化为一个非法日期的d3。Date的构造函数调用函数setDate检测月、日和年的合法性。如果月是非法的则置为1,年是非法的则置为1900,日是非法的则置为1。

驱动程序用重载的流插入运算符输出所建立的每一个Date对象。程序用重载的运算符+=将对象d2增加7天,用函数setDate将对象d3设置为1992年2月28日,接着将一个新对象d4设置为1969年3月18日并用重载的前置自增运算符将d4增加1天。为证实执行过程的正确性,在执行前置自增操作的前后分别输出了日期。最后,用重载的后置自增运算符将对象d4增加一天。为了证实执行的过程的正确性,在执行后置自增操作的前后也分别输出了日期。

重载前置自增运算符是简明直接的,前置自增运算符调用private工具函数helplncrement来执行实际的自增运算。函数 helpIncrement 必须要处理日期的边界情况,因为对某月的日期加1时,它可能已经达到了最大值,此时需要将月份加1并把日期置为1,如果月份已经是12,则必须将年份加1而月份置为1。函数helpIncrement使用函数leapYear和endofMonth正确地递增日期。

重载的前置自增运算符返回对当前对象Date(已自增)的引用。这是因为当前对象的*this作为Date&而返回。

重载后置自增运算符需要一点儿技巧。为模拟后置操作,函数必须返回该Date对象未自增的副本。在进入operator++时,函数先把当前对象(*this)保存在temp中,然后调用helpIncrement递增当前的Date对象,最后返回未递增的对象在temp中的副本。

注意这个函数不能返回对局部Date对象temp的引用,因为声明该对象的函数退出时删除了局部变量。这样,声明这个函数的返回类型为Date&将返回不复存在的对象的引用。返回局部变量的引用是个常见的错误,一些编译器会发出警告。