1. 日期类Date的设计与实现
在C++面向对象编程中,日期类(Date)是一个经典的教学案例,也是实际开发中常用的基础组件。这个看似简单的类实际上涉及了类设计、运算符重载、流操作等多个核心概念。我们先从最基础的类成员设计开始。
1.1 基础成员变量与构造函数
一个完整的日期类至少需要包含年、月、日三个成员变量。考虑到后续的运算和比较需求,我们采用整型存储:
cpp复制class Date {
private:
int _year;
int _month;
int _day;
};
构造函数的设计需要考虑多种初始化方式。最常见的是提供年月日的完整构造函数,以及缺省使用当前日期的默认构造函数:
cpp复制// 带参构造函数
Date(int year, int month, int day)
: _year(year), _month(month), _day(day) {
// 日期有效性校验
if (!IsValidDate()) {
throw std::invalid_argument("Invalid date");
}
}
// 默认构造函数(获取当前日期)
Date() {
time_t now = time(nullptr);
tm* local = localtime(&now);
_year = local->tm_year + 1900;
_month = local->tm_mon + 1;
_day = local->tm_mday;
}
注意:构造函数中必须包含日期有效性校验,否则后续运算可能产生非法日期。这里我们通过IsValidDate()私有方法实现校验。
1.2 日期有效性校验
日期校验需要考虑闰年、各月份天数等规则。这里我们实现IsValidDate()方法:
cpp复制bool Date::IsValidDate() const {
if (_year < 1 || _month < 1 || _month > 12 || _day < 1) {
return false;
}
static const int daysInMonth[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int maxDay = daysInMonth[_month];
// 处理闰年2月
if (_month == 2 && IsLeapYear()) {
maxDay = 29;
}
return _day <= maxDay;
}
bool Date::IsLeapYear() const {
return (_year % 400 == 0) || (_year % 100 != 0 && _year % 4 == 0);
}
1.3 基本运算符重载
日期类通常需要比较运算,我们可以重载相关运算符:
cpp复制bool Date::operator==(const Date& other) const {
return _year == other._year &&
_month == other._month &&
_day == other._day;
}
bool Date::operator<(const Date& other) const {
if (_year != other._year) return _year < other._year;
if (_month != other._month) return _month < other._month;
return _day < other._day;
}
// 其他比较运算符可以基于==和<实现
bool Date::operator!=(const Date& other) const { return !(*this == other); }
bool Date::operator<=(const Date& other) const { return *this < other || *this == other; }
bool Date::operator>
