The program of Figs. 9.4–9.6 enhances class Time
to demonstrate how arguments are implicitly passed to a constructor. The constructor defined in Fig. 9.2 initialized hour
, minute
and second
to 0
(i.e., midnight in universal time). Like other functions, constructors can specify default arguments. Line 13 of Fig. 9.4 declares the Time
constructor to include default arguments, specifying a default value of zero for each argument passed to the constructor. The constructor is declared explicit
because it can be called with one argument. We discuss explicit constructors in detail in Section 10.13.
1 // Fig. 9.4: Time.h
2 // Time class containing a constructor with default arguments.
3 // Member functions defined in Time.cpp.
4
5 // prevent multiple inclusions of header
6 #ifndef TIME_H
7 #define TIME_H
8
9 // Time class definition
10 class Time
11 {
12 public:
13 explicit Time( int = 0, int = 0, int = 0 ); // default constructor
14
15 // set functions
16 void setTime( int, int, int ); // set hour, minute, second
17 void setHour( int ); // set hour (after validation)
18 void setMinute( int ); // set minute (after validation)
19 void setSecond( int ); // set second (after validation)
20
21 // get functions
22 unsigned int getHour() const; // return hour
23 unsigned int getMinute() const; // return minute
24 unsigned int getSecond() const; // return second
25
26 void printUniversal() const; // output time in universal-time format
27 void printStandard() const; // output time in standard-time format
28 private:
29 unsigned int hour; // 0 - 23 (24-hour clock format)
30 unsigned int minute; // 0 - 59
31 unsigned int second; // 0 - 59
32 }; // end class Time
33
34 #endif
1 // Fig. 9.5: Time.cpp
2 // Member-function definitions for class Time.
3 #include <iostream>
4 #include <iomanip>
5 #include <stdexcept>
6 #include "Time.h" // include definition of class Time from Time.h
7 using namespace std;
8
9 // Time constructor initializes each data member
10 Time::Time( int hour, int minute, int second )
11 {
12 setTime( hour, minute, second ); // validate and set time
13 } // end Time constructor
14
15 // set new Time value using universal time
16 void Time::setTime( int h, int m, int s )
17 {
18 setHour( h ); // set private field hour
19 setMinute( m ); // set private field minute
20 setSecond( s ); // set private field second
21 } // end function setTime
22
23 // set hour value
24 void Time::setHour( int h )
25 {
26 if ( h >= 0 && h < 24 )
27 hour = h;
28 else
29 throw invalid_argument( "hour must be 0-23" );
30 } // end function setHour
31
32 // set minute value
33 void Time::setMinute( int m )
34 {
35 if ( m >= 0 && m < 60 )
36 minute = m;
37 else
38 throw invalid_argument( "minute must be 0-59" );
39 } // end function setMinute
40
41 // set second value
42 void Time::setSecond( int s )
43 {
44 if ( s >= 0 && s < 60 )
45 second = s;
46 else
47 throw invalid_argument( "second must be 0-59" );
48 } // end function setSecond
49
50 // return hour value
51 unsigned int Time::getHour() const
52 {
53 return hour;
54 } // end function getHour
55
56 // return minute value
57 unsigned Time::getMinute() const
58 {
59 return minute;
60 } // end function getMinute
61
62 // return second value
63 unsigned Time::getSecond() const
64 {
65 return second;
66 } // end function getSecond
67
68 // print Time in universal-time format (HH:MM:SS)
69 void Time::printUniversal() const
70 {
71 cout << setfill( '0' ) << setw( 2 ) << getHour() << ":"
72 << setw( 2 ) << getMinute() << ":" << setw( 2 ) << getSecond();
73 } // end function printUniversal
74
75 // print Time in standard-time format (HH:MM:SS AM or PM)
76 void Time::printStandard() const
77 {
78 cout << ( ( getHour() == 0 || getHour() == 12 ) ? 12 : getHour() % 12 )
79 << ":" << setfill( '0' ) << setw( 2 ) << getMinute()
80 << ":" << setw( 2 ) << getSecond() << ( hour < 12 ? " AM" : " PM" );
81 } // end function printStandard
1 // Fig. 9.6: fig09_06.cpp
2 // Constructor with default arguments.
3 #include <iostream>
4 #include <stdexcept>
5 #include "Time.h" // include definition of class Time from Time.h
6 using namespace std;
7
8 int main()
9 {
10 Time t1; // all arguments defaulted
11 Time t2( 2 ); // hour specified; minute and second defaulted
12 Time t3( 21, 34 ); // hour and minute specified; second defaulted
13 Time t4( 12, 25, 42 ); // hour, minute and second specified
14
15 cout << "Constructed with:
t1: all arguments defaulted
";
16 t1.printUniversal(); // 00:00:00
17 cout << "
";
18 t1.printStandard(); // 12:00:00 AM
19
20 cout << "
t2: hour specified; minute and second defaulted
";
21 t2.printUniversal(); // 02:00:00
22 cout << "
";
23 t2.printStandard(); // 2:00:00 AM
24
25 cout << "
t3: hour and minute specified; second defaulted
";
26 t3.printUniversal(); // 21:34:00
27 cout << "
";
28 t3.printStandard(); // 9:34:00 PM
29
30 cout << "
t4: hour, minute and second specified
";
31 t4.printUniversal(); // 12:25:42
32 cout << "
";
33 t4.printStandard(); // 12:25:42 PM
34
35 // attempt to initialize t6 with invalid values
36 try
37 {
38 Time t5( 27, 74, 99 ); // all bad values specified
39 } // end try
40 catch ( invalid_argument &e )
41 {
42 cerr << "
Exception while initializing t5: " << e.what() << endl;
43 } // end catch
44 } // end main
Constructed with:
t1: all arguments defaulted
00:00:00
12:00:00 AM
t2: hour specified; minute and second defaulted
02:00:00
2:00:00 AM
t3: hour and minute specified; second defaulted
21:34:00
9:34:00 PM
t4: hour, minute and second specified
12:25:42
12:25:42 PM
Exception while initializing t5: hour must be 0-23
In Fig. 9.5, lines 10–13 define the new version of the Time
constructor that receives values for parameters hour
, minute
and second
that will be used to initialize private
data members hour
, minute
and second
, respectively. The default arguments to the constructor ensure that, even if no values are provided in a constructor call, the constructor still initializes the data members. A constructor that defaults all its arguments is also a default constructor—that is, a constructor that can be invoked with no arguments. There can be at most one default constructor per class. The version of class Time
in this example provides set and get functions for each data member. The Time
constructor now calls setTime
, which calls the setHour
, setMinute
and setSecond
functions to validate and assign values to the data members.
Software Engineering Observation 9.5
Any change to the default argument values of a function requires the client code to be recompiled (to ensure that the program still functions correctly).
In Fig. 9.5, line 12 of the constructor calls member function setTime
with the values passed to the constructor (or the default values). Function setTime
calls setHour
to ensure that the value supplied for hour
is in the range 0–23, then calls setMinute
and setSecond
to ensure that the values for minute
and second
are each in the range 0–59. Functions setHour
(lines 24–30), setMinute
(lines 33–39) and setSecond
(lines 42–48) each throw an exception if an out-of-range argument is received.
Function main
in Fig. 9.6 initializes five Time
objects—one with all three arguments defaulted in the implicit constructor call (line 10), one with one argument specified (line 11), one with two arguments specified (line 12), one with three arguments specified (line 13) and one with three invalid arguments specified (line 38). The program displays each object in universal-time and standard-time formats. For Time
object t5
(line 38), the program displays an error message because the constructor arguments are out of range.