通过前面C++入门与类与对象的学习,今天我们将运用所学的知识点完成一个Date类。
六个成员函数,Date类只需要自己实现构造函数即可。
解析:
代码示例:
Date.h文件
class Date
{
public:
//Date类没有涉及动态资源的申请,所以析构、拷贝构造、赋值重载不用自己实现,使用编译器生成的即可
// 只有构造函数需要自己实现
//默认构造函数——内置类型需要自己实现,完成初始化
Date(int year = 2001, int month = 9, int day = 9);
//打印日期
void Print()const;
private:
int _year;//年
int _month;//月
int _day;//日
};
Date.cpp
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//打印日期
void Date::Print()const
{
cout << _year << "-" << _month << "-" << _day << endl;
}
解析:
Test.cpp
//测试构造函数
void TestDate1()
{
Date d1;
d1.Print();
const Date d2(2024, 1, 10);
d2.Print();
const Date d3(2024, 13, 1);
d3.Print();
}
int main()
{
TestDate1();
return 0;
}
运行结果:
通过测试,我们发现构造函数在初始化对象时,有一些非法日期也能成功初始化对象。
优化构造函数:在初始化之前,我们应当先检查月份与天数是否合理,合理则完成对象的初始化,不合理则提示并断言!
优化之后的代码:
//默认构造函数——内置类型需要自己实现,完成初始化
//注意缺省函数不能定义与声明都给缺省值,缺省值应当在函数声明指定
Date::Date(int year, int month, int day)
{
//检查月份与天数是否合理,合理才初始化,不合理提示并断言
if (month > 0 && month < 13 && day > 0 && day <= GetMonthDay(year,month))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "非法日期" << endl;
assert(false);
}
}
//获取月份的天数
int Date::GetMonthDay(const int year,const int month)const
{
//使用数组存放每个月的天数
//优化:因为该函数要被频繁调用,而局部变量每一次调用都要创建,所以将其优化为静态变量
static int daysArr[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//判断是否为闰年且为2月
//优化:因为闰年的判断麻烦,指令较多,所以先判断是否为2月
if (2 == month && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
return 29;
}
else
{
return daysArr[month];
}
}
解析:
自定义类型要使用运算符,需要通过运算符重载重新定义该运算符的含义。
使用运算符重载可以使用的程序更易于编写和阅读。
是否需要重载运算符,具体分析这个运算符对这个类是否有意义。
对于日期类我们一般可以对日期进行比较,所以日期类需要对关系运算符重载。
任意类,重载关系运算符:
代码示例:
Date.h
class Date
{
public:
//Date类没有涉及动态资源的申请,所以析构、拷贝构造、赋值重载不用自己实现,使用编译器生成的即可
// 只有构造函数需要自己实现
//默认构造函数——内置类型需要自己实现,完成初始化
Date(int year = 2001, int month = 9, int day = 9);
//获取月份的天数
int GetMonthDay(const int year,const int month)const;
//打印日期
void Print()const;
//关系运算符的重载
//1、<运算符重载
bool operator<(const Date& d)const;
//2、==运算符重载
bool operator==(const Date& d)const;
//3、<=运算符重载
bool operator<=(const Date& d)const;
//4、>运算符重载
bool operator>(const Date& d)const;
//5、>=运算符重载
bool operator>=(const Date& d)const;
//6、!=运算符重载
bool operator!=(const Date& d)const;
private:
int _year;//年
int _month;//月
int _day;//日
};
Date.cpp
//关系运算符的重载
//1、<运算符重载
bool Date::operator<(const Date& d)const
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day < d._day)
{
return true;
}
else
{
return false;
}
}
//2、==运算符重载
bool Date::operator==(const Date& d)const
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
//3、<=运算符重载
bool Date::operator<=(const Date& d)const
{
return *this < d || *this == d;
}
//4、>运算符重载
bool Date::operator>(const Date& d)const
{
return !(*this <= d);
}
//5、>=运算符重载
bool Date::operator>=(const Date& d)const
{
return !(*this < d);
}
//6、!=运算符重载
bool Date::operator!=(const Date& d)const
{
return !(*this == d);
}
解析:
Test.cpp
//测试日期的关系运算符重载
void TestDate2()
{
//普通对象
const Date d1;
//const对象
const Date d2(2024, 1, 10);
cout << (d1 < d2) << endl;
cout << (d1 == d2) << endl;
cout << (d1 <= d2) << endl;
cout << (d1 > d2) << endl;
cout << (d1 >= d2) << endl;
cout << (d1 != d2) << endl;
}
int main()
{
TestDate2();
return 0;
}
日期+日期是没有意义的,但是日期+天数有意义。
日期+天数,只需要理解日期的“进位制”即可。如图分析:
如图分析:我们可知日期+天数的进位制:
日期+天数有+与+=两种运算符重载可以完成。
注意:+=运算符会影响左操作数本身!
代码示例:
Date.cpp
//日期+=天数
Date& Date::operator+=(const int& day)
{
//1、日期的天数+天数
_day += day;
//使用变量存放GetMonthDay函数的返回值,避免重复调用
int ret = 0;
//while循环——天数满了进月份,月份满了进年
while (_day > (ret = GetMonthDay(_year, _month)))
{
//天数满了,减去当月的天数,月份进一
_day -= ret;
_month++;
//判断当月份满了,年份进一
if (_month > 12)
{
_month -= 12;
_year++;
}
}
//*this出了作用域还存在,所以返回值为引用返回
return *this;
}
解析:
注意:+运算符不会影响操作数!
代码示例:
//日期+天数
Date Date::operator+(const int& day)const
{
//+运算符不会影响操作数本身,所以定义一个局部变量来保存运算的日期
Date temp(*this);
temp._day += day;
int ret = 0;
while (temp._day > (ret = GetMonthDay(temp._year, temp._month)))
{
temp._day -= ret;
temp._month++;
if (temp._month > 12)
{
temp._month -= 12;
temp._year++;
}
}
//返回值为一个局部变量,出了作用域就不存在了,所以不能引用返回
return temp;
}
解析:
我们发现operator+与operator+=有许多代码是重复的,所以我们一般可以先实现operator+=,之后的operator+复用operator+=即可。
为什么复用operator+=,不复用operator+?
答案是:复用operator+=更好一些,因为operator+中需要创建两个额外的临时变量,而operator+=不需要创建。如下图所示:
如果+复用+=,只有+这里额外需要创建两个对象;如果是+=复用+,+=也需要额外创建两个对象。
代码示例:
//日期+天数复用+=
Date Date::operator+(const int& day)const
{
//+运算符不会影响操作数本身,所以定义一个局部变量来保存运算的日期
Date temp(*this);
temp += day;
//返回值为一个局部变量,出了作用域就不存在了,所以不能引用返回
return temp;
}
日期减天数也是有意义的。
日期加天数是进位,那日期减天数就是借位了。如下图所示:
如图分析:我们可知日期-天数的借位制:
注意:-=操作符会影响操作数本身。
代码示例:
//日期-=天数
Date& Date::operator-=(const int& day)
{
_day -= day;
//while循环——借位:如果天数<=0,则往月份去借。注意:当月份不够了,则往年去借。
while (_day <= 0)
{
//1、向月份借
_month--;
//注意:当月份不够了,则往年借
if (_month == 0)
{
_year--;
_month += 12;
}
_day += GetMonthDay(_year, _month);
}
//*this出了函数体还在,所以可以引用返回
return *this;
}
注意:向月份借完位之后,要先判断当月不够了,向年借位之后,才能获取天数。
注意:-操作符不会影响操作数本身,所以需要创建一个临时变量存放运算的日期。
与operator+一样的思路,operator-复用operator-=比较好。
代码示例:
//日期-天数
Date Date::operator-(const int& day)const
{
//-运算符不会影响操作数本身,所以定义一个临时变量存放运算的日期
Date temp(*this);
temp -= day;
//temp是一个局部变量,出了函数体就不存在,所以不能引用返回
return temp;
}
Test.cpp
//测试日期+天数与日期-天数
void TestDate3()
{
Date d1(2024, 1, 11);
Date d2;
//测试operator+
d2 = d1 + 100;
d1.Print();
d2.Print();
//测试operator+=
d1 += 100;
d1.Print();
//测试operator-
d2 = d1 - 100;
d1.Print();
d2.Print();
//测试operator-=
d1 -= 100;
d1.Print();
//特殊:日期加负数
d1 += -100;
d1.Print();
//特殊:日期减负数
d1 = d2 - (-100);
d1.Print();
}
int main()
{
TestDate3();
return 0;
}
我们发现当加减一个负数时,计算出错了。
因为我们operator-与operator+都是复用的operator-=与operator+=,所以我们直接定位这两个函数调试即可。
调试我们发现,原来在设计的时候我们没有考虑加减的天数为负数的情况。
当一个数加一个-100的数,实际是减去100;当一个数减-100时,实际是加100。
代码示例:
//日期+=天数
Date& Date::operator+=(const int& day)
{
//特殊情况:当加的天数为负数时,实际是减这个数的绝对值
if (day < 0)
{
return *this -= -day;
}
//1、日期的天数+天数
_day += day;
//使用变量存放GetMonthDay函数的返回值,避免重复调用
int ret = 0;
//while循环——天数满了进月份,月份满了进年
while (_day > (ret = GetMonthDay(_year, _month)))
{
//天数满了,减去当月的天数,月份进一
_day -= ret;
_month++;
//判断当月份满了,年份进一
if (_month > 12)
{
_month -= 12;
_year++;
}
}
//*this出了作用域还存在,所以返回值为引用返回
return *this;
}
//日期+天数复用+=
Date Date::operator+(const int& day)const
{
//+运算符不会影响操作数本身,所以定义一个局部变量来保存运算的日期
Date temp(*this);
temp += day;
//返回值为一个局部变量,出了作用域就不存在了,所以不能引用返回
return temp;
}
//日期-=天数
Date& Date::operator-=(const int& day)
{
//特殊情况:当减的天数为负数时,实际是加这个数的绝对值
if (day < 0)
{
return *this += -day;
}
_day -= day;
//while循环——借位:如果天数<=0,则往月份去借。注意:当月份不够了,则往年去借。
while (_day <= 0)
{
//1、向月份借
_month--;
//注意:当月份不够了,则往年借
if (_month == 0)
{
_year--;
_month += 12;
}
_day += GetMonthDay(_year, _month);
}
//*this出了函数体还在,所以可以引用返回
return *this;
}
//日期-天数
Date Date::operator-(const int& day)const
{
//-运算符不会影响操作数本身,所以定义一个临时变量存放运算的日期
Date temp(*this);
temp -= day;
//temp是一个局部变量,出了函数体就不存在,所以不能引用返回
return temp;
}
在内置类型中++操作符有前置++与后置++,所以运算符重载也应该有前置和后置两个版本。
因为前置与后置函数名都是operator++,并且运算对象的操作数类型与数量也相同,所以想要同时定义前置与后置两个版本必须先解决函数重载问题。
区分前置和后置操作符:
tip:前置类型返回的是递增后对象的引用。
能不能引用返回取决于,该对象出函数体是否存在,存在则可以引用返回,不存在则不可以。
代码演示:
//1、前置++
//前置++应该返回递增后对象的引用
Date& Date::operator++()
{
*this += 1;
//*this出了函数体还存在,所以引用返回
return *this;
}
tip:日期++就是日期+天数,所以复用operator+=。
tip:后置类型应该返回对象的原值(即递增之前的值),返回的形式是一个值而非引用。
代码示例:
//2、后置++
//后置++应该返回对象的原值(即递增之前的值),返回的形式是一个值而非引用
Date Date::operator++(int)
{
//定义一个临时变量存放递增之前的值
Date temp(*this);
*this += 1;
//temp是一个局部变量,出了函数就不存在了,所以返回的是一个值
return temp;
}
自定义类型前置比后置好:
与递增一样,递减也有前置与后置两个版本。
为了区分前置与后置,递减也是在后置增加了一个int参数。
前置类型返回的递减后对象的引用。
代码示例:
//1、前置--
//前置--应该返回递减后对象的引用
Date& Date::operator--()
{
//递减就是日期-天数,所以复用operator-=
*this -= 1;
//*this出了函数体还存在,所以引用返回
return *this;
}
后置类型应该返回对象的原值(即递减之前的值),返回的形式是一个值而非引用。
代码示例:
//2、后置--
//后置--应该返回对象的原值(即递减之前的值),返回的形式是一个值而非引用
Date Date::operator--(int)
{
//定义一个临时变量存放递减之前的值
Date temp(*this);
//递减就是日期-天数,所以复用operator-=
*this -= 1;
//temp是一个局部变量,出了函数就不存在了,所以返回的是一个值
return temp;
}
自定义类型前置比后置好:
日期-日期是有意义的,我们可以通过日期-日期计算两个日期之间的天数。
我们可以用计数器的方式,计算d1与d2两个日期之间的天数:
代码演示:
//日期-日期
int Date::operator-(const Date& d)const
{
//flag法
//1、假设max=*this,min=d,flag=1
Date max = *this;
Date min = d;
int flag = 1;//状态变量,为1表示状态成立,为-1表示状态不成立
//2、判断状态是否成立
if (*this < d)
{
//状态不成立
max = d;
min = *this;
flag = -1;
}
//通过计数器的方式,得到两个日期之间的天数
int count = 0;
while (min != max)
{
//自定义类型建议使用前置++
++min;
count++;
}
//返回的日期之差为两个日期之间的天数*flag
return count * flag;
}
C++IO标准库分别使用>>和<<执行输入和输出操作。如下图所示:
tip:
输入输出运算符重载函数必须是非成员函数:
IO运算符一般需要读写类的非公有数据成员,所以IO运算符一般被声明为友元类。
友元类:
友元函数在后期会详细讲解,今天大致知道使用即可。
tip:
代码示例:
//输出日期
//operator<<不能定义为成员函数,因为成员函数的左操作数被this占据
ostream& operator<<(ostream& out, const Date& d)
{
//输出日期
out << d._year << "年" << d._month << "月" << d._day;
//<<运算符从左向右结合,可以连续打印,所以operator<<要返回ostream形参
//ostream形参出了函数体还在,所以引用返回
return out;
}
tip: 因为内置类型的输出运算符不考虑格式化操作,尤其不会打印换行符,所以通常,重载输出运算符应该主要负责打印对象的内容而非控制格式,重载输出运算符不应该打印换行符。
tip:
代码示例:
//输入日期
istream& operator>>(istream& in, Date& d)
{
//输入运算符必须处理输入可能失败的情况
int year, month, day;//不需要初始化,因为我们将先读取数据到year,month, day,之后才使用
in >> year >> month >> day;
//检查输入是否成功且合理
if (in && month > 0 && month < 13 && day > 0 && day <= d.GetMonthDay(year, month))
{
//输入成功且合理
d._year = year;
d._month = month;
d._day = day;
}
else
{
//输入失败或不合理时,提示并断言
cout << "非法日期" << endl;
assert(false);
}
//输入运算符可以连续读取,所以operator>>要返回某个给定流的引用。
return in;
}
tip:
Date.h
#include
#include
using namespace std;
class Date
{
public:
//Date类没有涉及动态资源的申请,所以析构、拷贝构造、赋值重载不用自己实现,使用编译器生成的即可
// 只有构造函数需要自己实现
//默认构造函数——内置类型需要自己实现,完成初始化
Date(int year = 2001, int month = 9, int day = 9);
//获取月份的天数
int GetMonthDay(const int year,const int month)const;
//打印日期
void Print()const;
//关系运算符的重载
//1、<运算符重载
bool operator<(const Date& d)const;
//2、==运算符重载
bool operator==(const Date& d)const;
//3、<=运算符重载
bool operator<=(const Date& d)const;
//4、>运算符重载
bool operator>(const Date& d)const;
//5、>=运算符重载
bool operator>=(const Date& d)const;
//6、!=运算符重载
bool operator!=(const Date& d)const;
//日期+=天数
Date& operator+=(const int& day);
//日期+天数
Date operator+(const int& day)const;
//日期-=天数
Date& operator-=(const int& day);
//日期-天数
Date operator-(const int& day)const;
//递增
//区分前置与后置:后置增加了一个int参数,该参数一般不使用,仅仅是占位,与前置区分构成重载
//1、前置++
//前置++应该返回递增后对象的引用
Date& operator++();
//2、后置++
//后置++应该返回对象的原值(即递增之前的值),返回的形式是一个值而非引用
Date operator++(int);
//递减
//区分前置与后置:后置增加了一个int参数,该参数一般不使用,仅仅是占位,与前置区分构成重载
//1、前置--
//前置--应该返回递减后对象的引用
Date& operator--();
//2、后置--
//后置--应该返回对象的原值(即递减之前的值),返回的形式是一个值而非引用
Date operator--(int);
//日期-日期
int operator-(const Date& d)const;
//输出日期
//friend声明友元函数
friend ostream& operator<<(ostream& out, const Date& d);
//输入日期
//friend声明友元函数
friend istream& operator>>(istream& in, Date& d);
private:
int _year;//年
int _month;//月
int _day;//日
};
Date.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"Date.h"
//Date::Date(int year, int month, int day)
//{
// _year = year;
// _month = month;
// _day = day;
//}
//默认构造函数——内置类型需要自己实现,完成初始化
//注意缺省函数不能定义与声明都给缺省值,缺省值应当在函数声明指定
Date::Date(int year, int month, int day)
{
//检查月份与天数是否合理,合理才初始化,不合理提示并断言
if (month > 0 && month < 13 && day > 0 && day <= GetMonthDay(year,month))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "非法日期" << endl;
assert(false);
}
}
//获取月份的天数
int Date::GetMonthDay(const int year,const int month)const
{
//使用数组存放每个月的天数
//优化:因为该函数要被频繁调用,而局部变量每一次调用都要创建,所以将其优化为静态变量
static int daysArr[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//判断是否为闰年且为2月
//优化:因为闰年的判断麻烦,指令较多,所以先判断是否为2月
if (2 == month && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
return 29;
}
else
{
return daysArr[month];
}
}
//打印日期
void Date::Print()const
{
cout << _year << "-" << _month << "-" << _day << endl;
}
//关系运算符的重载
//1、<运算符重载
bool Date::operator<(const Date& d)const
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day < d._day)
{
return true;
}
else
{
return false;
}
}
//2、==运算符重载
bool Date::operator==(const Date& d)const
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
//3、<=运算符重载
bool Date::operator<=(const Date& d)const
{
return *this < d || *this == d;
}
//4、>运算符重载
bool Date::operator>(const Date& d)const
{
return !(*this <= d);
}
//5、>=运算符重载
bool Date::operator>=(const Date& d)const
{
return !(*this < d);
}
//6、!=运算符重载
bool Date::operator!=(const Date& d)const
{
return !(*this == d);
}
//日期+=天数
Date& Date::operator+=(const int& day)
{
//特殊情况:当加的天数为负数时,实际是减这个数的绝对值
if (day < 0)
{
return *this -= -day;
}
//1、日期的天数+天数
_day += day;
//使用变量存放GetMonthDay函数的返回值,避免重复调用
int ret = 0;
//while循环——天数满了进月份,月份满了进年
while (_day > (ret = GetMonthDay(_year, _month)))
{
//天数满了,减去当月的天数,月份进一
_day -= ret;
_month++;
//判断当月份满了,年份进一
if (_month > 12)
{
_month -= 12;
_year++;
}
}
//*this出了作用域还存在,所以返回值为引用返回
return *this;
}
//日期+天数
//Date Date::operator+(const int& day)const
//{
// //+运算符不会影响操作数本身,所以定义一个局部变量来保存运算的日期
// Date temp(*this);
// temp._day += day;
// int ret = 0;
// while (temp._day > (ret = GetMonthDay(temp._year, temp._month)))
// {
// temp._day -= ret;
// temp._month++;
// if (temp._month > 12)
// {
// temp._month -= 12;
// temp._year++;
// }
// }
// //返回值为一个局部变量,出了作用域就不存在了,所以不能引用返回
// return temp;
//}
//日期+天数复用+=
Date Date::operator+(const int& day)const
{
//+运算符不会影响操作数本身,所以定义一个局部变量来保存运算的日期
Date temp(*this);
temp += day;
//返回值为一个局部变量,出了作用域就不存在了,所以不能引用返回
return temp;
}
//日期-=天数
Date& Date::operator-=(const int& day)
{
//特殊情况:当减的天数为负数时,实际是加这个数的绝对值
if (day < 0)
{
return *this += -day;
}
_day -= day;
//while循环——借位:如果天数<=0,则往月份去借。注意:当月份不够了,则往年去借。
while (_day <= 0)
{
//1、向月份借
_month--;
//注意:当月份不够了,则往年借
if (_month == 0)
{
_year--;
_month += 12;
}
_day += GetMonthDay(_year, _month);
}
//*this出了函数体还在,所以可以引用返回
return *this;
}
//日期-天数
Date Date::operator-(const int& day)const
{
//-运算符不会影响操作数本身,所以定义一个临时变量存放运算的日期
Date temp(*this);
temp -= day;
//temp是一个局部变量,出了函数体就不存在,所以不能引用返回
return temp;
}
//递增
//区分前置与后置:后置增加了一个int参数,该参数一般不使用,仅仅是占位,与前置区分构成重载
//1、前置++
//前置++应该返回递增后对象的引用
Date& Date::operator++()
{
*this += 1;
//*this出了函数体还存在,所以引用返回
return *this;
}
//2、后置++
//后置++应该返回对象的原值(即递增之前的值),返回的形式是一个值而非引用
Date Date::operator++(int)
{
//定义一个临时变量存放递增之前的值
Date temp(*this);
*this += 1;
//temp是一个局部变量,出了函数就不存在了,所以返回的是一个值
return temp;
}
//递减
//区分前置与后置:后置增加了一个int参数,该参数一般不使用,仅仅是占位,与前置区分构成重载
//1、前置--
//前置--应该返回递减后对象的引用
Date& Date::operator--()
{
//递减就是日期-天数,所以复用operator-=
*this -= 1;
//*this出了函数体还存在,所以引用返回
return *this;
}
//2、后置--
//后置--应该返回对象的原值(即递减之前的值),返回的形式是一个值而非引用
Date Date::operator--(int)
{
//定义一个临时变量存放递减之前的值
Date temp(*this);
//递减就是日期-天数,所以复用operator-=
*this -= 1;
//temp是一个局部变量,出了函数就不存在了,所以返回的是一个值
return temp;
}
//日期-日期
int Date::operator-(const Date& d)const
{
//flag法
//1、假设max=*this,min=d,flag=1
Date max = *this;
Date min = d;
int flag = 1;//状态变量,为1表示状态成立,为-1表示状态不成立
//2、判断状态是否成立
if (*this < d)
{
//状态不成立
max = d;
min = *this;
flag = -1;
}
//通过计数器的方式,得到两个日期之间的天数
int count = 0;
while (min != max)
{
//自定义类型建议使用前置++
++min;
count++;
}
//返回的日期之差为两个日期之间的天数*flag
return count * flag;
}
//输出日期
//operator<<不能定义为成员函数,因为成员函数的左操作数被this占据
ostream& operator<<(ostream& out, const Date& d)
{
//输出日期
out << d._year << "年" << d._month << "月" << d._day;
//<<运算符从左向右结合,可以连续打印,所以operator<<要返回ostream形参
//ostream形参出了函数体还在,所以引用返回
return out;
}
//输入日期
istream& operator>>(istream& in, Date& d)
{
//输入运算符必须处理输入可能失败的情况
int year, month, day;//不需要初始化,因为我们将先读取数据到year,month, day,之后才使用
in >> year >> month >> day;
//检查输入是否成功且合理
if (in && month > 0 && month < 13 && day > 0 && day <= d.GetMonthDay(year, month))
{
//输入成功且合理
d._year = year;
d._month = month;
d._day = day;
}
else
{
//输入失败或不合理时,提示并断言
cout << "非法日期" << endl;
assert(false);
}
//输入运算符可以连续读取,所以operator>>要返回某个给定流的引用。
return in;
}
Test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"Date.h"
//测试构造函数
void TestDate1()
{
Date d1;
d1.Print();
const Date d2(2024, 1, 10);
d2.Print();
const Date d3(2024, 13, 1);
d3.Print();
}
//测试日期的关系运算符重载
void TestDate2()
{
//普通对象
const Date d1;
//const对象
const Date d2(2024, 1, 10);
cout << (d1 < d2) << endl;
cout << (d1 == d2) << endl;
cout << (d1 <= d2) << endl;
cout << (d1 > d2) << endl;
cout << (d1 >= d2) << endl;
cout << (d1 != d2) << endl;
}
//测试日期+天数与日期-天数
void TestDate3()
{
Date d1(2024, 1, 11);
Date d2;
//测试operator+
d2 = d1 + 100;
d1.Print();
d2.Print();
//测试operator+=
d1 += 100;
d1.Print();
//测试operator-
d2 = d1 - 100;
d1.Print();
d2.Print();
//测试operator-=
d1 -= 100;
d1.Print();
//特殊:日期加负数
d1 += -100;
d1.Print();
//特殊:日期减负数
d1 = d2 - (-100);
d1.Print();
}
//测试递增
void TestDate4()
{
Date d1;
Date d2;
d2 = d1++;
d1.Print();
d2.Print();
d2 = ++d1;
d1.Print();
d2.Print();
}
//测试递减
void TestDate5()
{
Date d1;
Date d2;
d2 = d1--;
d1.Print();
d2.Print();
d2 = --d1;
d1.Print();
d2.Print();
}
//测试日期-日期
void TestDate6()
{
Date d1(2023, 12, 1);
Date d2(2024, 12, 31);
cout << d1 - d2 << endl;
cout << d2 - d1 << endl;
}
//测试输入输出日期
void TestDate7()
{
Date d1(2023, 12, 1);
//测试operator<<
cout << d1 << endl;
//测试operator>>
cin >> d1;
cout << d1 << endl;
}
int main()
{
//TestDate1();
//TestDate2();
//TestDate3();
//TestDate4();
//TestDate5();
//TestDate6();
TestDate7();
return 0;
}