【发布时间】:2014-10-18 03:54:59
【问题描述】:
我有两个类,Time 和 Date,Date 由 Time 对象组成。我对时间对象有疑问。测试程序(我不允许更改)创建一个时间对象,然后它创建一个日期对象并将时间对象作为参数传递。第一次创建时间对象时,它会正确初始化,但是当调用 Date 对象构造函数时,它不使用原始时间对象中的参数。相反,它会创建一个新的 Time 对象并使用我的默认参数 (0,0,0),这需要包含在我的 Time 构造函数和 Time 类定义中。
我想要做的是将提供给 Time 对象的参数传递给 Date 构造函数的 Time 参数,以便 Time 构造函数不使用默认的 (0,0,0) 参数。我尝试使用对时间对象的引用,但我无法让它工作。
这是我的两个类头和测试代码。请注意,不允许更改测试代码。我想只是在创建日期对象时将参数添加到它,但是不允许更改该代码。
测试代码:
#include <iostream>
using std::cout;
using std::endl;
#include "Time.h" // include Time class definition
#include "Date.h" // include Date class definition
const int MAX_TICKS = 20;
int main()
{
Time t(23, 59, 58);// create a time object
Date d(12, 31, 2014, t); // create date object
// output Time object t's values
for ( int ticks = 1; ticks < MAX_TICKS; ++ticks )
{
d.print(); // invokes print
cout << endl;
d.tick(); // invokes function tick
} // end for
d.~Date();// call Date destructor
system("PAUSE");
return 0;
} // end main
日期标题:
#ifndef DATE_H
#define DATE_H
#include "Time.h"
class Date
{
public:
static const unsigned int monthsPerYear = 12; // months in a year
Date( int = 1, int = 1, int = 1900, Time = Time()); // default constructor
~Date(); // provided to confirm destruction order
void print() const; // print date in month/day/year format
void tick(); // function that increments seconds by 1.
void increaseADay(); // increases the day by one
private:
unsigned int month; // 1-12 (January-December)
unsigned int day; // 1-31 based on month
unsigned int year; // any year
Time time; // private Time object - class composition
// utility function to check if day is proper for month and year
unsigned int checkDay( int );
}; // end class Date
#endif
时间标题:
#ifndef TIME_H
#define TIME_H
// Time class definition
class Time
{
public:
explicit Time( int = 0, int = 0, int = 0 ); // default constructor
~Time(); // destructor
// set functions
void setTime( int, int, int ); // set hour, minute, second
void setHour( int ); // set hour (after validation)
void setMinute( int ); // set minute (after validation)
void setSecond( int ); // set second (after validation)
// get functions
unsigned int getHour() const; // return hour
unsigned int getMinute() const; // return minute
unsigned int getSecond() const; // return second
void printUniversal() const; // output time in universal-time format
void printStandard() const; // output time in standard-time format
private:
unsigned int hour; // 0 - 23 (24-hour clock format)
unsigned int minute; // 0 - 59
unsigned int second; // 0 - 59
}; // end class Time
#endif
日期类实现文件:
// Date class member-function definitions.
#include <array>
#include <iostream>
#include <stdexcept>
#include "Date.h" // include Date class definition
#include "Time.h" // include the Time class definition
using namespace std;
// constructor confirms proper value for month; calls
// utility function checkDay to confirm proper value for day
Date::Date( int mn, int dy, int yr, Time time)
{
if ( mn > 0 && mn <= monthsPerYear ) // validate the month
month = mn;
else
throw invalid_argument( "month must be 1-12" );
year = yr; // could validate yr
day = checkDay( dy ); // validate the day
// output Date object to show when its constructor is called
cout << "Date object constructor for date ";
print();
cout << endl;
} // end Date constructor
// print Date object in form month/day/year
void Date::print() const
{
cout << month << '/' << day << '/' << year;
cout << "\t";
time.printStandard();
cout << "\t";
time.printUniversal();
} // end function print
// output Date object to show when its destructor is called
Date::~Date()
{
cout << "Date object destructor for date ";
print();
cout << endl;
} // end ~Date destructor
// function to increment Time by one second
void Date::tick()
{
int tempSecond = time.getSecond();
if (tempSecond < 59)
{
tempSecond++;
time.setSecond(tempSecond);
}
else if (tempSecond >= 59)
{
time.setSecond(0);
int tempMin = time.getMinute();
if (tempMin < 59)
{
tempMin++;
time.setMinute(tempMin);
}
else if (tempMin >= 59)
{
time.setMinute(0);
int tempHour = time.getHour();
if (tempHour < 23)
{
tempHour++;
time.setHour(tempHour);
}
else if (tempHour >= 23)
{
time.setHour(0);
increaseADay();
}
}
}
}
void Date::increaseADay()
{
checkDay(++day);
}
// utility function to confirm proper day value based on
// month and year; handles leap years, too
unsigned int Date::checkDay( int testDay )
{
static const array< int, monthsPerYear + 1 > daysPerMonth =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
// determine whether testDay is valid for specified month
if ( testDay > 0 && testDay <= daysPerMonth[ month ] )
return testDay;
// February 29 check for leap year
if ( month == 2 && testDay == 29 && ( year % 400 == 0 ||
( year % 4 == 0 && year % 100 != 0 ) ) )
return testDay;
if (testDay > daysPerMonth[month])
{
month++;
day = 1;
if (month > monthsPerYear)
{
year++;
month = 1;
day = 1;
return 0;
}
}
throw invalid_argument( "Invalid day for current month and year" );
} // end function checkDay
时间类实现文件
#include <iostream>
#include <iomanip>
#include <stdexcept>
#include "Time.h" // include definition of class Time from Time.h
using namespace std;
// Time constructor initializes each data member
Time::Time( int hour, int minute, int second )
{
cout << "Time object constructor is called ";
setTime( hour, minute, second ); // validate and set time
cout << "\t";
printStandard(); // call the print standard function
cout << "\t";
printUniversal(); // call the print universal function.
cout << endl;
} // end Time constructor
// Time destructor - calls printStandard and printUniversal
Time::~Time()
{
// print a message indicating that we are destructing
cout << "Time object destructor called.";
// call printStandard and printUniversal functions
printStandard();
printUniversal();
} // end Time destructor
// set new Time value using universal time
void Time::setTime( int h, int m, int s )
{
setHour( h ); // set private field hour
setMinute( m ); // set private field minute
setSecond( s ); // set private field second
} // end function setTime
// set hour value
void Time::setHour( int h )
{
if ( h >= 0 && h < 24 ) // validate the input
hour = h;
else // throw an error if hour is not valid.
throw invalid_argument( "hour must be 0-23" );
} // end function setHour
// set minute value
void Time::setMinute( int m )
{
if ( m >= 0 && m < 60 ) // validate the input
minute = m;
else // throw an error if hour is not valid.
throw invalid_argument( "minute must be 0-59" );
} // end function setMinute
// set second value
void Time::setSecond( int s )
{
if ( s >= 0 && s < 60 )
second = s;
else
throw invalid_argument( "second must be 0-59" );
} // end function setSecond
// return hour value
unsigned int Time::getHour() const
{
return hour;
} // end function getHour
// return minute value
unsigned int Time::getMinute() const
{
return minute;
} // end function getMinute
// return second value
unsigned int Time::getSecond() const
{
return second;
} // end function getSecond
// print Time in universal-time format (HH:MM:SS)
void Time::printUniversal() const
{
// set field widths and fill characters to print format "00:00:00"
// setfill is sticky, setw is not
cout << setfill( '0' ) << setw( 2 ) << getHour() << ":"
<< setw( 2 ) << getMinute() << ":" << setw( 2 ) << getSecond();
} // end function printUniversal
// print Time in standard-time format (HH:MM:SS AM or PM)
void Time::printStandard() const
{
// set field widths and fill characters to print format "00:00:00"
// use the conditional operator to check if time is equal to 0 or 12
// if so, mod the hour by 12 to put it in 12 hour clock format.
cout << ( ( getHour() == 0 || getHour() == 12 ) ? 12 : getHour() % 12 )
<< ":" << setfill( '0' ) << setw( 2 ) << getMinute()
<< ":" << setw( 2 ) << getSecond() << ( hour < 12 ? " AM" : " PM" );
} // end function printStandard
如果您运行它并查看控制台输出的前两行,它会显示时间构造函数打印设置的时间。第二个打印显示如何再次调用时间构造函数,将数据成员设置为 00:00:00。这是我试图避免的。我不明白为什么第二次调用 Time 构造函数...
【问题讨论】:
-
对于初学者来说,你明确地调用了析构函数,当
d在main结束时再次被销毁时,这会导致未定义的行为,所以你剩下的问题几乎没有实际意义,直到你解决这个问题。还有太多不相关的代码,并且没有任何代码可以真正解释您的问题。请用mvce 重写您的问题。 -
如果您指的是测试代码中的显式析构函数调用,我不允许更改它。这是我的老师提供的代码,他说我的对象必须使用这个......
-
除非你的老师告诉你“请不要在真正的代码中这样做”,否则我会非常怀疑他的 C++ 教学能力。显式调用不仅是错误的,而且绝对没有任何目的,
d将在t之前被销毁。我看到你已经剥离了代码,但你仍然没有为你的构造函数提供定义。请再次阅读 mvce 链接,您需要发布可以按原样复制、粘贴和编译的内容。 -
我同意你对他的 C++ 教学能力的怀疑。过去,当他对我使用新的 C++11 类内数据成员初始化功能的作业打分时,我已经不得不纠正他。当他因为使用推荐的 Array 类模板而不是内置 C 样式数组而对我进行评分时,我也不得不纠正他。可悲的是,他仍然是我的老师,我仍然必须使用他给我的东西。关于我的代码,如果我包含所有内容会更好,包括我的两个类实现文件。我不能把零件剪下来并期望它编译...
-
没关系,只要能编译。我猜析构函数调用在那里,否则
d不会被销毁,直到调用pause以保持命令窗口打开。这很容易解决,方法是从打开的命令窗口运行应用程序,或者通过引入新的块范围来强制在调用pause之前销毁t和d。
标签: c++ constructor composition