当前位置: 首页 > news >正文

【C++】日期类

鼠鼠实现了一个日期类,用来练习印证前几篇博客介绍的内容!!

目录

1.日期类的定义 

2.得到某年某月的天数

 3.检查日期是否合法

 4.(全缺省)构造函数

5.拷贝构造函数 

6.析构函数

7.赋值运算符重载 

8.>运算符重载 

9.==运算符重载

 10.>=运算符重载

11.<运算符重载 

12.<=运算符重载 

13.!=运算符重载 

14.日期 += 天数 

15.日期+天数 

16.日期-=天数

17.日期-天数

18.前置++

19.后置++

20.前置-- 

21.后置--

22.日期-日期,返回天数 

 23.流插入运算符重载

24.流提取运算符重载 

25.test 


本鼠创建一个工程,工程包含三个文件,分别是Date.h、Date.cpp和test.cpp。 

1.日期类的定义 

本鼠对日期类的定义如下,放在了Date.h文件中:

class Date
{int _year;int _month;int _day;
public:inline int GetMonth_day()const//得到某年某月的天数{const int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (this->_month == 2 && (this->_year % 4 == 0 && this->_year % 100 != 0 || this->_year % 400 == 0)){return 29;}return a[this->_month];}bool Check()const;//检查日期是否合法Date(int year = 1, int month = 1, int day = 1);//(全缺省)构造函数Date(const Date& d);//拷贝构造函数~Date();//析构函数Date& operator=(const Date& d)//赋值运算符重载{this->_year = d._year;this->_month = d._month;this->_day = d._day;}bool operator>(const Date& d)const;//>运算符重载bool operator==(const Date& d)const;//==运算符重载bool operator>=(const Date& d)const;//>=运算符重载bool operator<(const Date& d)const;//<运算符重载bool operator<=(const Date& d)const;//<=运算符重载bool operator!=(const Date& d)const;//!=运算符重载Date& operator+=(int day);//日期+=天数Date operator+(int day)const;//日期+天数Date& operator-=(int day);//日期-=天数Date operator-(int day)const;//日期-天数Date& operator++();//前置++Date operator++(int);//后置++Date& operator--();//前置--Date operator--(int);//后置--int operator-(const Date& d)const;//日期-日期,返回天数friend ostream& operator<<(ostream& cout, const Date& d);//友元函数:流插入运算符重载friend istream& operator>>(istream& cin, Date& d);//友元函数:流提取运算符重载
};

本鼠对于成员函数大部分都采取声明和定义分离的方式。成员变量无非就是年、月、日呗。还运用了友元的知识。如上代码所示。

2.得到某年某月的天数

 对于这个日期类所要实现的成员函数中有很多场景我们需要得到某年某月的天数,所以我们将这个功能实现成函数。又因为需要频繁调用这个函数,我们将他实现成内联函数。

声明和定义:

inline int GetMonth_day()const//得到某年某月的天数{const int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (this->_month == 2 && (this->_year % 4 == 0 && this->_year % 100 != 0 || this->_year % 400 == 0)){return 29;}return a[this->_month];}

注意:

  • 该函数的实现思路过于简单,本鼠就不解释了!
  • 内联函数声明和定义不可分离,又因为日期类的成员函数需频繁调用这个函数,所以我们将其声明和定义都实现在类里面。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

 3.检查日期是否合法

例如构造函数可能构造了非法的日期,所以我们将检查日期是否合法这个功能实现成函数。

定义:

bool Date::Check()const//检查日期是否合法
{if (this->_year < 0 ||this->_month < 0 || this->_month > 12 ||this->_day<0 || this->_day>GetMonth_day()){return true;}return false;
}

注意:

  • 该函数的实现思路:我们这个日期类不支持公元前的年份。所以当this指针指向对象的日期:年小于0、月小于0、月大于12、日小于0、日大于该日期应得天数这几项但凡有一项为真时,说明日期非法,返回真;否则,返回假。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

 4.(全缺省)构造函数

我们分析日期类对象的初始化需求,若使用编译器生成的默认构造函数是达不到需求的,所以我们自己显式实现构造函数。

定义:

Date::Date (int year , int month , int day )//(全缺省)构造函数
{this->_year = year;this->_month = month;this->_day = day;if (Check()){cout << "构造了日期非法:" << *this << endl;}
}

注意:

  • 该函数的实现思路无非就是将第2、3、4个形参的年、月、日初始化this指针指向对象的成员变量(年、月、日),若形参没有接收到实参的拷贝,使用缺省值。
  • 需要检查this指针指向对象的日期是否合法。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 缺省参数不能在函数声明和定义中同时出现,当函数声明和定义分离时在声明给缺省参数 。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

5.拷贝构造函数 

这个日期类不涉及资源申请,其实不用我们显式实现拷贝构造函数,用编译器生成的默认拷贝构造函数就行 ,本鼠显式实现就是练练手。

定义:

Date::Date(const Date& d)//拷贝构造函数
{this->_year = d._year;this->_month = d._month;this->_day = d._day;
}

注意:

  • 该函数的实现思路:第一个形参是隐藏的this指针,第二个形参是已存在对象的引用。 用第二个形参的成员变量初始化this指针指向的正在创建对象的成员变量。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

6.析构函数

这个日期类的析构函数其实也不用我们自己显式实现的,练练手。

定义:

Date::~Date()//析构函数
{this->_year = this->_month = this->_day = 0;
}

注意:

  • ​​​不妨将this指针指向对象的成员变量赋值成0就行 ,其实函数体内为空也无妨。反正这个日期类没有申请资源,当对象生命周期结束后系统会将其内存收归就行。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

7.赋值运算符重载 

其实这个函数也不用我们自己显式实现的,练练手。

 声明和定义:

	Date& operator=(const Date& d)//赋值运算符重载{this->_year = d._year;this->_month = d._month;this->_day = d._day;return *this;}

注意:

  • 该函数实现思路:第二个形参是已存在对象的引用。用第二个形参的成员变量赋值给this指针指向对象的成员变量就行。
  • 为了支持连续赋值,需要返回左操作数本身(拷贝也行)。
  • 赋值运算符只能重载成类的成员函数不能重载成全局函数。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

8.>运算符重载 

定义:

bool Date::operator>(const Date& d)const//>运算符重载
{if (this->_year > d._year){return true;}else if (this->_year == d._year){if (this->_month > d._month){return true;}else if (this->_month == d._month){return this->_day > this->_day;}}return false;
}

注意:

  • 该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:若第一个操作数的年大于第二个操作数的年,返回真;若第一个操作数的年等于第二个操作数的年,那就若第一个操作数的月大于第二个操作数的月,返回真;若第一个操作数的年和月都等于第二个操作数的年和月,那就若第一个操作数的日大于第二个操作数的日,返回真;其余情况都返回假。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

9.==运算符重载

定义:

bool Date::operator==(const Date& d)const//==运算符重载
{return this->_year == d._year && this->_month == d._month && this->_day == d._day;
}

注意: 

  •  该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数实现思路:第一个操作数的年、月、日都等于第二个操作数的年、月、日,返回真;否则,返回假。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

 10.>=运算符重载

定义:

bool Date:: operator>=(const Date& d)const//>=运算符重载
{return *this > d || *this == d;
}

注意: 

  •  该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:若第一个操作数大于或者等于第二个操作数(调用>运算符重载和==运算符重载),返回真;否则,返回假。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

11.<运算符重载 

定义:

bool Date::operator<(const Date& d)const//<运算符重载
{return !(*this >= d);
}

 注意:

  • 该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:返回>=运算符重载的逻辑取反就好。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

12.<=运算符重载 

定义:

bool Date::operator<=(const Date& d)const//<=运算符重载
{return !(*this > d);
}

注意:

  • 该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:返回>运算符重载的逻辑取反就好。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

13.!=运算符重载 

定义:

bool Date::operator!=(const Date& d)const//!=运算符重载
{return !(*this == d);
}

注意:

  • 该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:返回==运算符重载的逻辑取反就好。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

14.日期 += 天数 

这个函数本鼠想要的是日期+天数后,日期本身发生改变形成新日期并返回。 

定义:

Date& Date::operator+=(int day) //日期 += 天数
{this->_day += day;while (this->_day > GetMonth_day()){this->_day -= GetMonth_day();this->_month++;if (this->_month > 12){this->_month = 1;this->_year++;}}return *this;
}

注意:

  • 该函数的实现思路: this指针指向对象的日期的日+=天数。循环:日若超过“当年当月”该有的天数,说明月该+1;就让日-“当年当月”该有的天数,并++月;若是月超过12,年份就该+1;…………直到日小于“当年当月”该有的天数循环停止。思想本质就跟我们做加法运算是一样的,有时又要向高位进位。。
  • 该函数的返回值*this出了该函数作用域还存在,可以用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

15.日期+天数 

这个函数本鼠想要的是日期+天数后,日期本身不发生改变,却要返回日期+天数后的结果。

定义:

Date Date::operator+(int day)const//日期+天数
{Date tmp = *this;tmp += day;return tmp;
}

注意:

  • 该函数的实现思路:通过拷贝构造函数创建一个与this指针指向对象一样的临时对象,让临时对象+=天数,返回临时对象就好了。
  • 该函数的返回值是临时对象,出了该函数的作用域就不存在了,所以不能用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

16.日期-=天数

这个函数本鼠想要的是日期-天数后,日期本身发生改变形成新日期并返回。 

定义:

Date& Date::operator-=(int day)//日期-=天数
{this->_day -= day;while (this->_day <= 0){this->_month--;if (this->_month < 1){this->_year--;this->_month = 12;}this->_day += GetMonth_day();}return *this;
}

注意:

  • 该函数的实现思路:this指针指向对象的日-=天数。循环:日若小于或等于0,说明月该-1;月--后需要判断月是否小于1,如果月小于1,年份就该-1;日+=“当年当月”该有的天数;…………直到日大于0循环停止。思想本质跟我们做减法运算是一样的,有时候要跟高位借位呗。。
  • 该函数的返回值*this出了该函数作用域还存在,可以用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

17.日期-天数

这个函数本鼠想要的是日期-天数后,日期本身不发生改变,却要返回日期-天数后的结果。

定义:

Date Date::operator-(int day)const//日期-天数
{Date tmp = *this;tmp -= day;return tmp;
}
  • 该函数的实现思路:通过拷贝构造函数创建一个与this指针指向对象一样的临时对象,让临时对象-=天数,返回临时对象就好了。
  • 该函数的返回值是临时对象,出了该函数的作用域就不存在了,所以不能用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

18.前置++

前置++:日期本身+1,返回日期+1之后的结果。

定义:

Date& Date::operator++()//前置++
{*this += 1;return *this;
}

注意:

  • 这个函数实现思想过于简单,不解释了。
  •  该函数的返回值*this出了该函数作用域还存在,可以用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

19.后置++

后置++:先使用后+1,因此需要返回+1之前的旧值。日期本身+1,返回日期+1之前的旧日期。

定义:

Date Date::operator++(int)//后置++
{Date tmp = *this;*this += 1;return tmp;
}

注意:

  • 这个函数实现思想过于简单,不解释。
  • 后置++重载时多增加一个int类型的参数,不显式调用函数时该参数不用传递,编译器自动传递;显式调用该函数,那么一定要传入一个任意int整形以区分前置++。
  • 这个函数的返回值是临时变量,出了该函数作用域就不存在了,所以不能用引用返回。
  •  该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

20.前置-- 

前置--:日期本身-1,返回日期-1之后的结果。

定义:

Date& Date::operator--()//前置--
{*this -= 1;return *this;
}

注意:

  • 这个函数实现思想过于简单,不解释了。
  •  该函数的返回值*this出了该函数作用域还存在,可以用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

21.后置--

后置--:先使用后-1,因此需要返回-1之前的旧值。日期本身-1,返回日期-1之前的旧日期。

定义:

Date Date::operator--(int)//后置--
{Date tmp = *this;*this -= 1;return tmp;
}

注意:

  • 这个函数实现思想过于简单,不解释。
  • 后置--重载时多增加一个int类型的参数,不显式调用函数时该参数不用传递,编译器自动传递;显式调用该函数,那么一定要传入一个任意int整形以区分前置--。
  • 这个函数的返回值是临时变量,出了该函数作用域就不存在了,所以不能用引用返回。
  •  该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

22.日期-日期,返回天数 

这个函数本鼠想要获取日期之间夹杂着多少天呗。如果第一个日期大于第二个日期,返回的天数是负数;反之,为正数。

定义:

int Date::operator-(const Date& d)const//日期-日期,返回天数
{Date max = *this;Date min = d;int flag = -1;if (max < min){flag = 1;max = d;min = *this;}int n = 0;while (max != min){min++;n++;}return n * flag;
}

注意: 

  • 这个函数实现思路简单,本鼠就不解释了。
  •  该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

 23.流插入运算符重载

介绍流插入运算符重载之前,我们需要回顾这里C++的输入&&输出介绍过的知识:cout是库里面的ostream类型的全局对象。

对于流插入运算符重载,本鼠并没有将其重载成日期类的成员函数,而是重载成全局函数,为啥?


我们先看流插入运算符一般的使用场景如下:

#include<iostream>
using namespace std;
int main()
{int a = 10;int b = 20;cout << a << ' ' << b << endl;return 0;
}

我们分析:

  • 分析1:对于流插入操作符<<来说,是有两个操作数的,第一个应该对象cout,第二个是需要“流向”控制台的对象
  • 分析2:流插入操作符<<需要支持连续输出,如这里:
cout << a << ' ' << b << endl;

这句语句的结合性是从左往右的,cout<<a的返回值是对象cout,这个返回值cout又作为cout<<' '的左操作数,cout<<' '的返回值又是对象cout,这个返回值cout又作为cout<<b的左操作数…………

如果我们将流插入运算符重载重载成日期类的成员函数的话,我们想想当我们在主函数调用的情景必然是这样的:

int main()
{Date d1;d1.operator<<(cout);//显式调用d1. << cout;//不显式调用return 0;
}

可是这样子的话代码的可读性不好,好像是cout通过<<“流向” d1一样。不符合我们对分析1的分析。


那该如何是好呢?其中一个办法就是将流插入运算符重载重载成全局函数。

那么将其重载成全局函数的话,也采用声明和定义分离,为了支持连续输出,返回值应该是对象cout。

声明,声明在Date.h文件中:

ostream& operator<<(ostream& cout, const Date& d);//流插入运算符重载

定义,定义在Date.cpp文件中:

ostream& operator<<(ostream& cout, const Date& d)//流插入
{cout << d._year << '/' << d._month << '/' << d._day ;return cout;
}

我们没有将其重载成全局函数,日期类的成员变量又是被访问限定符private修饰的,那么在这个全局函数中无权访问对象的成员变量啊。所以我们在日期类中用到友元函数:

friend ostream& operator<<(ostream& cout, const Date& d);//友元函数:流插入运算符重载

24.流提取运算符重载 

 介绍流提取运算符重载之前,我们需要回顾这里C++的输入&&输出介绍过的知识:cin是库里面的istream类型的全局对象。

流提取运算符重载的问题和流插入运算符重载的问题差不多,不介绍了。

流提取运算符重载重载成全局函数,采取声明和定义分离,为了支持连续输入,返回值应该是对象cin。

声明,声明在Date.h文件中:

ostream& operator<<(ostream& cout, const Date& d);//流插入运算符重载

定义,定义在Date.cpp文件中:

istream& operator>>(istream& cin,  Date& d)//流提取{cout << "请输入日期并以回车键结束" << endl;while (1){cin >> d._year >> d._month >> d._day;if (d.Check()){cout << "输入日期非法" << endl;}else{break;}}return cin;}

不同的是,这里流提取可以给一定的提示,如:请输入日期并以回车键结束。检查输入的日期是否合法也是必须的。

日期类中用到友元函数:

friend istream& operator>>(istream& cin, Date& d);//友元函数:流提取运算符重载

25.test 

 全部代码如下,可以在test.cpp中测试代码,有兴趣可以玩玩。

Date.h:

#pragma once
#include<stdbool.h>
#include<iostream>
using namespace std;
class Date
{int _year;int _month;int _day;
public:inline int GetMonth_day()const//得到某年某月的天数{const int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (this->_month == 2 && (this->_year % 4 == 0 && this->_year % 100 != 0 || this->_year % 400 == 0)){return 29;}return a[this->_month];}bool Check()const;//检查日期是否合法Date(int year = 1, int month = 1, int day = 1);//(全缺省)构造函数Date(const Date& d);//拷贝构造函数~Date();//析构函数Date& operator=(const Date& d)//赋值运算符重载{this->_year = d._year;this->_month = d._month;this->_day = d._day;return *this;}bool operator>(const Date& d)const;//>运算符重载bool operator==(const Date& d)const;//==运算符重载bool operator>=(const Date& d)const;//>=运算符重载bool operator<(const Date& d)const;//<运算符重载bool operator<=(const Date& d)const;//<=运算符重载bool operator!=(const Date& d)const;//!=运算符重载Date& operator+=(int day);//日期+=天数Date operator+(int day)const;//日期+天数Date& operator-=(int day);//日期-=天数Date operator-(int day)const;//日期-天数Date& operator++();//前置++Date operator++(int);//后置++Date& operator--();//前置--Date operator--(int);//后置--int operator-(const Date& d)const;//日期-日期,返回天数friend ostream& operator<<(ostream& cout, const Date& d);//友元函数:流插入运算符重载friend istream& operator>>(istream& cin, Date& d);//友元函数:流提取运算符重载
};ostream& operator<<(ostream& cout, const Date& d);//流插入运算符重载istream& operator>>(istream& cin,  Date& d);//流提取运算符重载

Date.cpp:

#include"Date.h"
bool Date::Check()const//检查日期是否合法
{if (this->_year < 0 ||this->_month < 0 || this->_month > 12 ||this->_day<0 || this->_day>GetMonth_day()){return true;}return false;
}Date::Date (int year , int month , int day )//(全缺省)构造函数
{this->_year = year;this->_month = month;this->_day = day;if (Check()){cout << "构造了日期非法:" << *this << endl;}
}Date::Date(const Date& d)//拷贝构造函数
{this->_year = d._year;this->_month = d._month;this->_day = d._day;
}Date::~Date()//析构函数
{this->_year = this->_month = this->_day = 0;
}bool Date::operator>(const Date& d)const//>运算符重载
{if (this->_year > d._year){return true;}else if (this->_year == d._year){if (this->_month > d._month){return true;}else if (this->_month == d._month){return this->_day > this->_day;}}return false;
}bool Date::operator==(const Date& d)const//==运算符重载
{return this->_year == d._year && this->_month == d._month && this->_day == d._day;
}bool Date:: operator>=(const Date& d)const//>=运算符重载
{return *this > d || *this == d;
}bool Date::operator<(const Date& d)const//<运算符重载
{return !(*this >= d);
}bool Date::operator<=(const Date& d)const//<=运算符重载
{return !(*this > d);
}bool Date::operator!=(const Date& d)const//!=运算符重载
{return !(*this == d);
}Date& Date::operator+=(int day) //日期 += 天数
{this->_day += day;while (this->_day > GetMonth_day()){this->_day -= GetMonth_day();this->_month++;if (this->_month > 12){this->_month = 1;this->_year++;}}return *this;
}Date Date::operator+(int day)const//日期+天数
{Date tmp = *this;tmp += day;return tmp;
}Date& Date::operator-=(int day)//日期-=天数
{this->_day -= day;while (this->_day <= 0){this->_month--;if (this->_month < 1){this->_year--;this->_month = 12;}this->_day += GetMonth_day();}return *this;
}Date Date::operator-(int day)const//日期-天数
{Date tmp = *this;tmp -= day;return tmp;
}Date& Date::operator++()//前置++
{*this += 1;return *this;
}Date Date::operator++(int)//后置++
{Date tmp = *this;*this += 1;return tmp;
}Date& Date::operator--()//前置--
{*this -= 1;return *this;
}Date Date::operator--(int)//后置--
{Date tmp = *this;*this -= 1;return tmp;
}int Date::operator-(const Date& d)const//日期-日期,返回天数
{Date max = *this;Date min = d;int flag = -1;if (max < min){flag = 1;max = d;min = *this;}int n = 0;while (max != min){min++;n++;}return n * flag;
}ostream& operator<<(ostream& cout, const Date& d)//流插入
{cout << d._year << '/' << d._month << '/' << d._day ;return cout;
}istream& operator>>(istream& cin,  Date& d)//流提取{cout << "请输入日期并以回车键结束" << endl;while (1){cin >> d._year >> d._month >> d._day;if (d.Check()){cout << "输入日期非法,请重新输入" << endl;}else{break;}}return cin;}

test.cpp:

#include"Date.h"
int main()
{Date d1(2003, 12, 12);Date d2 = d1;cout << d1 << endl << d2 << endl;cout << (d1 > d2) << endl;cout << (d1 >= d2) << endl;cout << (d1 < d2) << endl;cout << (d1 <= d2) << endl;cout << (d1 == d2) << endl;cout << (d1 != d2) << endl;Date d3;cout << d3 << endl;cin >> d3 >> d2 >> d1;cout << d3 <<endl<< d2 <<endl<< d1 << endl;return 0;
}

 运行结果,符合预期:

 感谢阅读!!!!

相关文章:

【C++】日期类

鼠鼠实现了一个日期类&#xff0c;用来练习印证前几篇博客介绍的内容&#xff01;&#xff01; 目录 1.日期类的定义 2.得到某年某月的天数 3.检查日期是否合法 4.&#xff08;全缺省&#xff09;构造函数 5.拷贝构造函数 6.析构函数 7.赋值运算符重载 8.>运算符重…...

力扣热100 滑动窗口

这里写目录标题 3. 无重复字符的最长子串438. 找到字符串中所有字母异位词 3. 无重复字符的最长子串 左右指针left和right里面的字符串一直是没有重复的 class Solution:def lengthOfLongestSubstring(self, s: str) -> int:# 左右指针leftright0ans0#初始化结果tablecolle…...

三万字带你一遍跑通uer

三万字带你一遍跑通uer 参考文档 今天给大家介绍个非常强大的项目uer&#xff0c;集成了许多可以做自然语言的东西&#xff0c;效果的话也非常好&#xff0c;很适合企业级的应用&#xff01; 1. 先将项目uer从github拉取下来&#xff08;zip或git都ok&#xff09; 2. 用pycha…...

Ubuntu24.04LTS基础软件下载

librewolf: deb文件link 作用&#xff1a;访问github&#xff0c;无痕浏览&#xff0c;这个速度&#xff0c;不指望了 vscodium: 从deb安装&#xff0c;ubuntu sudo dpkg -i xxx.debpaste-image 插件替代 markdown wps: libreoffice: 替换USTC源 sudo nano /etc/apt/sourc…...

SQLAlchemy配置连接多个数据库

1.定义配置项 首先定义两个数据库的配置信息 # PostgreSQL database configuration DB_USERNAMEpostgres DB_PASSWORDpassord DB_HOST127.0.0.1 DB_PORT5432 DB_DATABASEtest# mysql database configuration DB_USERNAME_MYSQLroot DB_PASSWORD_MYSQLpassword DB_HOST_MYSQL127…...

NLP+LLM从入门到精通系列

NLPLLM从入门到精通系列 前言&#xff1a;笔者从事于NLPLLM的对话智能机器人的相关行业&#xff0c;现在的大模型的技术日新月异&#xff0c;传统的NLP业务显然是要被淘汰的&#xff0c;那么这也是我着笔写这一系列文章的初衷。本系列将由浅到深&#xff0c;结合实际代码案例&…...

用数组手搓一个小顶堆

堆默认从数组下标为1开始存储。 const int N201000; int heap[N]; int len; 插入操作&#xff1a; 将元素插入到堆的末尾位置向上调整。 void up(int k){while(k>1&&heap[k/2]>heap[k]){swap(heap[k],heap[k/2]);k/2;} } //len为当前存在元素长度 void Inser…...

【Linux开发】基于ALSA库实现音量调节

基于ALSA库实现音量调节 ALSA库实现音量调节1、使用alsamixer工具查看音频接口2、完整代码2.1、snd_mixer_open2.2、snd_mixer_attach、2.3、snd_mixer_selem_register2.4、snd_mixer_load2.5、snd_mixer_first_elem/snd_mixer_elem_next2.6、snd_mixer_selem_get_playback_vol…...

代理IP在未来将面临哪些挑战?

今天我们来聊聊代理IP在未来可能会面临的挑战。虽然代理IP技术目前应用广泛&#xff0c;但随着科技的发展和网络环境的变化&#xff0c;代理IP也将面临一些新的挑战。让我们一起来看看这些挑战是什么吧&#xff01; 1. 更严格的网络封锁和检测 现代社会各行各业都在飞速发展&…...

FineBI在线学习资源-数据处理

FineBI在线学习资源汇总&#xff1a; 学习资源 视频课程 帮助文档 问答 数据处理学习文档&#xff1a; 相关资料&#xff1a; 故事背景概述-https://help.fanruan.com/finebi6.0/doc-view-1789.html 基础表处理-https://help.fanruan.com/finebi6.0/doc-view-1791.html …...

【代码随想录算法训练营第37期 第四十五天 | LeetCode198.打家劫舍、213.打家劫舍II、337.打家劫舍III】

代码随想录算法训练营第37期 第四十五天 | LeetCode198.打家劫舍、213.打家劫舍II、337.打家劫舍III 一、198.打家劫舍 解题代码C&#xff1a; class Solution { public:int rob(vector<int>& nums) {if (nums.size() 0) return 0;if (nums.size() 1) return num…...

Elasticsearch查询上下文和_source

查询上下文 {"took": 1,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 1,"relation"…...

golang实现网卡流量监控

获取当前时刻一分钟前的网卡流量排序 package mainimport ("fmt""github.com/mackerelio/go-osstat/network""log""net/http""sort""strconv""time" )var arr []map[string]int var arr2 []map[string]…...

技术分享:直播平台如何开发并接入美颜SDK

本篇文章&#xff0c;笔者将分享直播平台如何开发并接入美颜SDK的技术细节与步骤。 一、选择合适的美颜SDK 首先&#xff0c;选择一款适合的美颜SDK非常重要。市面上有很多优秀的美颜SDK供应商&#xff0c;选择时应考虑以下因素&#xff1a; 功能丰富性&#xff1a;支持美白…...

左耳听风_114_113_Go编程模式修饰器

你好&#xff0c;我是陈浩&#xff0c;我名多尔多house.之前呢我写过一篇文章叫做python修饰器的函数式编程。 那这种模式呢可以很轻松的把一些函数啊装配到另外一些函数上。 让你的代码呢更加简单&#xff0c;也可以让一些小功能性的代码复用性更高。 让代码中的函数呢可以…...

Java实习手册(小白也看得懂)

秃狼说 距离俺发布的学习路线已经六个月了&#xff0c;那我给小伙伴的学习周期是四五个月左右&#xff0c;我相信大多的小伙伴已经学习的差不多了。正好赶上暑期实习的阶段&#xff0c;在暑期找到实习就成为暑期的头等大事。 实习经验在校招的起到决定性的作用&#xff0c;所…...

Elasticsearch 分析器(Analyzer)的作用和配置

在Elasticsearch中&#xff0c;分析器&#xff08;Analyzer&#xff09;是文本处理的核心组件&#xff0c;它负责将输入的文本转换为可用于搜索和索引的词项&#xff08;tokens&#xff09;。这一过程涉及多个步骤&#xff0c;包括字符过滤、分词和标记过滤&#xff0c;共同决定…...

SpringBoot(一)创建一个简单的SpringBoot工程

Spring框架常用注解简单介绍 SpringMVC常用注解简单介绍 SpringBoot&#xff08;一&#xff09;创建一个简单的SpringBoot工程 SpringBoot&#xff08;二&#xff09;SpringBoot多环境配置 SpringBoot&#xff08;三&#xff09;SpringBoot整合MyBatis SpringBoot&#xff08;四…...

简述Vue中的数据双向绑定原理

Vue中的数据双向绑定原理是Vue框架的核心特性之一&#xff0c;它通过数据劫持结合发布者-订阅者模式来实现。下面将详细阐述Vue中数据双向绑定的原理&#xff0c;并尽量按照清晰的结构进行归纳&#xff1a; 一、数据劫持 使用Object.defineProperty()&#xff1a; Vue在组件…...

C++STL函数对象的应用

STL函数对象 文章目录 STL函数对象1.基本概念2.使用方法1. 简单函数对象示例2. 函数对象作为算法参数3. Lambda表达式作为函数对象 2.一元谓词和二元谓词1.一元谓词2.二元谓词3.总结 3.算术仿函数1.使用示例2.Lambda表达式的替代 4.关系仿函数5.逻辑仿函数 C中的函数对象&#…...

AJAX-day1:

注&#xff1a;文件布局&#xff1a; 一、AJAX的概念&#xff1a; AJAX是浏览器与服务器进行数据通信的技术 >把数据变活 二、AJAX的使用&#xff1a; 使用axios库&#xff0c;与服务器进行数据通信 基于XMLHttpRequest封装&#xff0c;代码简单 Vue,React项目使用 学习…...

昆虫学(书籍学习资料)

包括昆虫分类&#xff08;上下册&#xff09;、昆虫生态大图鉴等书籍资料。...

springboot + mybatis 多数据源切换

参考的b站博主写的 配置文件: spring:datasource:db1:jdbc-url: jdbc:mysql://localhost:3306/interview_database?useUnicodetrue&characterEncodingutf-8&useSSLfalseusername: rootpassword: 12345driver-class-name: com.mysql.cj.jdbc.Driverdb2:jdbc-url: jdbc…...

windows电脑网络重置后wifi列表消失怎么办?

我们的电脑网络偶尔会出现异常&#xff0c;我们通常会下意识选择网络诊断&#xff0c;运行完诊断后一般会让我们选择重置网络&#xff0c;然而&#xff0c;重置后wifi列表突然消失&#xff0c;无法愉快地上网了&#xff0c;找了一圈&#xff0c;都说是更改适配器选项&#xff0…...

Python + 在线 + 文生音,音转文(中文文本转为英文语音,语音转为中文文本)

开源模型 平台&#xff1a;https://huggingface.co/ars-语言转文本: pipeline("automatic-speech-recognition", model"openai/whisper-large-v3", device0 ) hf: https://huggingface.co/openai/whisper-large-v3 github: https://github.com/openai/wh…...

哏号分治,CF103D - Time to Raid Cowavans

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 103D - Time to Raid Cowavans 二、解题报告 1、思路分析 想了半天数据结构最终选择根号分治 我们考虑 大于 550 的公差直接暴力 小于550 的公差的所有询问&#xff0c;我们直接计算该公差后缀和&#xf…...

基于深度学习的图像背景剔除

在过去几年的机器学习领域&#xff0c;我一直想打造真正的机器学习产品。 几个月前&#xff0c;在参加了精彩的 Fast.AI 深度学习课程后&#xff0c;似乎一切皆有可能&#xff0c;我有机会&#xff1a;深度学习技术的进步使许多以前不可能实现的事情成为可能&#xff0c;而且开…...

Python使用(...)连接字符串

Python 字符串连接的灵活性。 使用括号来组织多行字符串时的自动拼接。 e e var_str g*3connect_str (fa{e}bcvar_strh )print(connect_str) print(type(connect_str)) 运行结果&#xff1a; aebcgggh <class str> 解释&#xff1a; 定义变量&#xff1a; e e:…...

鸿蒙:1.入门

概述 简介 鸿蒙操作系统&#xff08;HarmonyOS&#xff09;是华为公司发布的一款智能终端系统&#xff0c;是基于微内核的面向全场景的分布式操作系统。它致力于提供更加安全、高效、低延迟、低功耗的操作体验&#xff0c;可通过技术手段对应用程序和设备进行智能协同&#xf…...

【matlab】智能优化算法——求解目标函数

智能优化算法在求解目标函数方面发挥着重要作用&#xff0c;它通过迭代、筛选等方法来寻找目标函数的最优值&#xff08;极值&#xff09;。以下是关于智能优化算法求解目标函数的详细介绍&#xff1a; 一、智能优化算法概述 智能优化算法是一种搜索算法&#xff0c;旨在通过…...

不改代码,实现web.config或app.config的连接字符串加密解密

目的&#xff1a;加密字符串&#xff0c;防止明文显示。 好处&#xff1a;不用修改代码&#xff0c;微软自带功能&#xff0c;自动解密。 web.config 参考相关文章&#xff1a; Walkthrough: Encrypting Configuration Information Using Protected Configuration | Microso…...

Python创建MySQL数据库

一、使用Docker部署本地MySQL数据库 docker run --restartalways -p 3307:3306 --name mysql -e MYSOL_ROOT_PASSWORDlms123456 -d mysql:8.0.25 参数解析: 用户名:root 密码:lms123456 端口:3307 二、在Pycharm开发工具中配置连接MySQL数据库 三、安装zdppy_mysql pip inst…...

【C++】unordered系列容器的封装

你很自由 充满了无限可能 这是很棒的事 我衷心祈祷你可以相信自己 无悔地燃烧自己的人生 -- 东野圭吾 《解忧杂货店》 unordered系列的封装 1 unordered_map 和 unordered_set2 改造哈希桶2.1 模版参数2.2 加入迭代器 3 上层封装3.1 unordered_set3.2 unordered_map 4 面…...

matlab 超越椭圆函数图像绘制

matlab 超越椭圆函数图像绘制 超越椭圆函数图像绘制xy交叉项引入斜线负向斜线成分正向斜线成分 x^2 y^2 xy 1 &#xff08;负向&#xff09;绘制结果 x^2 y^2 - xy 1 &#xff08;正向&#xff09;绘制结果 超越椭圆函数图像绘制 xy交叉项引入斜线 相对于标准圆&#xf…...

本地文件同步上传到Gitee远程仓库

1、打开我们的项目所在文件夹 2、在项目文件夹【鼠标右击】弹出菜单&#xff0c;在【鼠标右击】弹出的菜单中&#xff0c;点击【Git Bash Here】&#xff0c;弹出运行窗口&#xff08;前提条件是已装好git环境&#xff09; 3、在命令窗口中输入&#xff1a;git init 4、在 Gite…...

RESTful Web 服务详解

RESTful Web 服务是一种基于 Representational State Transfer (REST) 架构风格的 Web 服务&#xff0c;它利用 HTTP 协议来传输数据&#xff0c;支持多种数据格式如 JSON 和 XML。在 Spring 框架中&#xff0c;通过简单配置和注解可以轻松实现 RESTful Web 服务。在本文中&…...

【ARMv8/v9 GIC 系列 5.3 -- 系统寄存器对中断的处理】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 ARMv8/v9系统寄存器对中断的控制Group 0中断的寄存器Group 1中断的寄存器安全状态与中断分组中断处理过程中断确认处理代码中断完成处理代码ARMv8/v9系统寄存器对中断的控制 在ARM GIC 体系结构中,中断分组通过一系列系统寄存器进…...

MUNIK解读ISO26262--系统架构

功能安全之系统阶段-系统架构 我们来浅析下功能安全系统阶段重要话题——“系统架构” 目录概览&#xff1a; 系统架构的作用系统架构类型系统架构层级的相关安全机制梳理 1.系统架构的作用 架构的思维包括抽象思维、分层思维、结构化思维和演化思维。通过将复杂系统分解…...

STM32第十五课:LCD屏幕及应用

文章目录 需求一、LCD显示屏二、全屏图片三、数据显示1.显示欢迎词2.显示温湿度3.显示当前时间 四、需求实现代码 需求 1.在LCD屏上显示一张全屏图片。 2.在LCD屏上显示当前时间&#xff0c;温度&#xff0c;湿度。 一、LCD显示屏 液晶显示器&#xff0c;简称 LCD(Liquid Cry…...

Java--继承

1.继承的本质是对某一批类的抽象&#xff0c;从而实现对世界更好的建模 2.extends的意思是“扩展”&#xff0c;子类是父亲的扩展 3.Java中只有单继承&#xff0c;没有多继承 4.继承关系的两个类&#xff0c;一个为子类&#xff08;派生类&#xff09;&#xff0c;一个为父类…...

Github与本地仓库建立链接、Git命令(或使用Github桌面应用)

一、Git命令&#xff08;不嫌麻烦可以使用Github桌面应用&#xff09; git clone [] cd [] git branch -vv #查看本地对应远程的分支对应关系 git branch -a #查看本地和远程所有分支 git checkout -b [hongyuan] #以当前的本地分支作为基础新建一个【】分支,命名为h…...

c++之旅第十一弹——顺序表

大家好啊&#xff0c;这里是c之旅第十一弹&#xff0c;跟随我的步伐来开始这一篇的学习吧&#xff01; 如果有知识性错误&#xff0c;欢迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 创作不易&#xff0c;希望大家多多支持哦&#xff01; 一,数据结构…...

深入了解 PXE:定义、架构、原理、应用场景及常见命令体系

引言 PXE&#xff08;Preboot Execution Environment&#xff0c;预启动执行环境&#xff09;是一种允许计算机通过网络启动操作系统而无需本地存储设备的技术。本文将详细介绍 PXE 的定义、架构、原理、应用场景及常见命令体系&#xff0c;特别是以 CentOS 为例&#xff0c;展…...

《每天5分钟用Flask搭建一个管理系统》第9章:API设计

第9章&#xff1a;API设计 9.1 RESTful API的概念 RESTful API是一种基于HTTP协议的网络服务接口设计方法&#xff0c;它使用标准的HTTP方法&#xff0c;如GET、POST、PUT、DELETE等&#xff0c;来执行资源的操作。 9.2 Flask-RESTful扩展的使用 Flask-RESTful是一个Flask扩…...

CCM的作用及原理

CCM调试的理论依据_ccm矩阵sat调试-CSDN博客 CCM是在WB之后&#xff0c;就是当AWB将白色校正之后其他颜色也会跟着有明显变化&#xff0c;CCM的作用就是要保持白色不变&#xff0c;把其他色彩校正到非常精准的地步。 校正后的颜色(target值是一个固定的值)CCM矩阵*原始的颜色…...

10.09面试题目记录

艾融软件 - 线上面试题 排序算法的时间复杂度 O(n^2&#xff09;&#xff1a;冒泡&#xff0c;选择&#xff0c;插入 O(logn&#xff09;&#xff1a;折半插入排序 O(nlogn)&#xff1a;希尔&#xff0c;归并&#xff0c;快速&#xff0c;堆 O(nk)&#xff1a;桶&#xff0c;…...

14-29 剑和诗人3 – 利用知识图谱增强 LLM 推理能力

知识图谱提供了一种结构化的方式来表示现实世界的事实及其关系。通过将知识图谱整合到大型语言模型中&#xff0c;我们可以增强它们的事实知识和推理能力。让我们探索如何实现这一点。 知识图谱构建 在利用知识图谱进行语言模型增强之前&#xff0c;我们需要从可靠的来源构建…...

【代码大全2 选读】看看骨灰级高手消灭 if-else 逻辑的瑞士军刀长啥样

文章目录 1 【写在前面】2 【心法】这把瑞士军刀长啥样3 【示例1】确定某个月份的天数&#xff08;Days-in-Month Example&#xff09;4 【示例2】确定保险费率&#xff08;Insurance Rates Example&#xff09;5 【示例3】灵活的消息格式&#xff08;Flexible-Message-Format …...

深度学习 --- stanford cs231学习笔记八(训练神经网络之dropout)

6&#xff0c;dropout 6&#xff0c;1 线性分类器中的正则化 在线性分类器中&#xff0c;我们提到过正则化&#xff0c;其目的就是为了防止过度拟合。例如&#xff0c;当我们要用一条curve去拟合一些散点的数据时&#xff0c;常常是不希望训练出来的curve过所有的点&#xff0c…...

【C++】 解决 C++ 语言报错:Undefined Reference

文章目录 引言 未定义引用&#xff08;Undefined Reference&#xff09;是 C 编程中常见的错误之一&#xff0c;通常在链接阶段出现。当编译器无法找到函数或变量的定义时&#xff0c;就会引发未定义引用错误。这种错误会阻止生成可执行文件&#xff0c;影响程序的正常构建。本…...