经历前期C语言的学习,C语言的编程思路是面向过程的编程,将所需要实现的功能封装为每一个功能函数,在主函数中进行调用
C++编程思想是面向对象的编程,相比较于C语言的编程,它更具有更高的安全性和可维护性,C++的特性将功能利用类进行抽象后进行封装,之后在通过创建对象实现功能调用
基于基础C++11标准下新特性,主要通过运算符重载来实现日期类
首先来了解运算符重载的特性:
运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意:
1,不能通过连接其他符号来创建新的操作符:比如operator@
2,重载操作符必须有一个类类型或者枚举类型的操作数
3,用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义
4,作为类成员的重载函数时,有一个默认的形参this,限定为第一个形参
5,.* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载
7,编译器会默认生成赋值运算符重载,完成值拷贝
日期类中主要以年 月 日 作为成员变量,同时为了实现C++类的封装,将其设定为私有成员变量
private:
int _y;
int _m;
int _d;
为了初始化类对象的创建,编译器默认的构造函数为无参构造函数,这里自定义带默认参数的构造函数初始化类对象
Date(int y = 1900, int m = 1, int d = 1)
{
//判断初始化日期是否有效
if (y <= 0 || m <= 0 || m > 12 || d <= 0 || d > getDay(y,m))
{
_y = 1;
_m = 1;
_d = 1;
cout<<"日期无效"<
由于日期类中,其成员变量均为int整型,构造函数也仅仅为简单的赋值操作,没有开辟内存空间,不需要资源释放,对此析构函数的功能不明显
具体对于析构函数的理解参照构造,析构,拷贝构造核心点总结
类似于上述析构函数的分析,简单的值拷贝,不涉及内存空间拷贝,对此日期类中拷贝构造函数为浅拷贝
但是需要注意 拷贝构造函数的形参为const引用类型,以免引起值拷贝递归调用
具体对于拷贝构造函数的理解参照构造,析构,拷贝构造核心点总结
Date(const Date& d)
{
_y = d._y;
_m = d._m;
_d = d._d;
}
传入参数为一个int整型的天数
首先判断传入天数是否为一个负数 +=一个负数等于-=一个正数
以类成员变量天数_d加天数判断是否溢出
根据溢出天数进行月份进位 以及年份进位和月份归1
进位过程需要通过一个while循环判断,判断条件为天数<当前月份天数结束循环
int getDay(int y, int m)
{
static int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int day = days[m];
if (m == 2 && (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)))
{
day += 1;//二月 闰年 多一天 29
}
return day;
}
Date& operator+=(int day)//日期+=运算
{
//判断日期是否为负数
if (day < 0)
{
return *this -= -day;
}
_d += day;
//判断天数是否溢出
while (_d > getDay(_y, _m))
{
_d -= getDay(_y,_m);//计算溢出天数
//月份进位
_m++;
if (_m == 12)
{
_y++;
_m = 1;//月份归1,年份进位
}
}
return *this;//左操作数即为this指针指向
}
传入参数为一个int整型的天数
首先判断传入天数是否为一个负数 -=一个负数等于+=一个正数
以类成员变量天数_d减去天数判断是否需要前一个月的天数来进行补偿
根据所需补偿天数进行月份退位 以及年份退位和月份归12
由于需要前一个月天数来补偿,所以先考虑退位,再进行补偿天数计算
进位过程需要通过一个while循环判断,判断条件为天数>0结束循环
Date& operator-=(int day)//日期-=运算
{
//判断日期是否为负数
if (day < 0)
{
return *this += -day;
}
_d -= day;
//判断天数是否为负数
while (_d < 0)
{
//月份退位,前一个月的天数来进行补偿
_m--;
if (_m == 0)
{
_y--;
_m = 12;//月份归12,年份退位
}
_d += getDay(_y, _m);//计算补偿天数
}
return *this;//左操作数即为this指针指向
}
日期的加减操作,其需要注意,左操作数不为返回值,所需左操作数不会被修改,需要创建新对象作为返回值 进行值传递
Date operator+(int day)//日期+运算 d=d1+90; d1本身不会被修改 而是值传递
{
Date tmp = *this;
return tmp += day;//+=操作重载
}
Date operator-(int day)//日期-运算 d=d1-90; d1本身不会被修改 而是值传递
{
Date tmp = *this;
return tmp -= day;//+=操作重载
}
自加运算符自身改变,所以返回类型为引用,且参数为默认this指针,返回this指针解引用+1或-1
//前置++
Date& operator++()//本身改变 可以返回引用
{
return *this += 1;
}
//前置--
Date& operator--()//本身改变 可以返回引用
{
return *this -= 1;
}
后置自加操作,自身先不改变,等传值结束后,再进行加1操作
this指向左操作数 左操作数先赋值后才会改变 需要创建临时对象作为返回值
//后置++ 与前置++构成重载 参数加入int
Date operator++(int)
{
Date tmp = *this;
*this += 1;
return tmp;
}
//后置-- 与前置--构成重载 参数加入int
Date operator--(int)
{
Date tmp = *this;
*this -= 1;
return tmp;
}
关系判断包括 == != > < >= <=
其中形参包括隐含this和显示创建的常引用类型d
返回值为bool类型 作为关系判断条件
bool operator==(const Date& d)
{
return _y == d._y&&_m == d._m&&_d == d._d;
}
bool operator!=(const Date& d)
{
return !(*this==d);
}
bool operator>(const Date&d)
{
if (_y > d._y)
{
return true;
}
else if (_y == d._y)
{
if (_m > d._m)
return true;
else if (_m == d._m)
{
if (_d > d._d)
{
return true;
}
}
}
return false;
}
bool operator<(const Date& d)
{
return !(*this >= d);
}
bool operator>=(const Date& d)
{
return (*this > d) || (*this == d);
}
bool operator<=(const Date& d)
{
return !(*this >= d);
}
综合之前所写的运算符重载函数包括++ += -= --等,再次基础上完成
相隔天数计算:小日期经过多少次自加与大日期相同
//日期相减 相差天数
int operator-(const Date& d)
{
//小日期经过多少次自加与大日期相同
Date max = *this;
Date min = d;
int flag = 1;
if (max < min)
{
max = d;
min = *this;
flag = -1;
}
int day = 0;
while (min < max)
{
++min;
++day;
}
return flag * day;
}
#include
using namespace std;
class Date
{
public:
Date(int y = 1900, int m = 1, int d = 1)
{
//判断初始化日期是否有效
if (y <= 0 || m <= 0 || m > 12 || d <= 0 || d > getDay(y,m))
{
_y = 1;
_m = 1;
_d = 1;
cout<<"日期无效"< getDay(_y, _m))
{
_d -= getDay(_y,_m);//计算溢出天数
//月份进位
_m++;
if (_m == 12)
{
_y++;
_m = 1;//月份归1,年份进位
}
}
return *this;//左操作数即为this指针指向
}
Date& operator-=(int day)//日期-=运算
{
//判断日期是否为负数
if (day < 0)
{
return *this += -day;
}
_d -= day;
//判断天数是否为负数
while (_d < 0)
{
//月份退位,前一个月的天数来进行补偿
_m--;
if (_m == 0)
{
_y--;
_m = 12;//月份归12,年份退位
}
_d += getDay(_y, _m);//计算补偿天数
}
return *this;//左操作数即为this指针指向
}
Date operator+(int day)//日期+运算 d=d1+90; d1本身不会被修改 而是值传递
{
Date tmp = *this;
return tmp += day;//+=操作重载
}
Date operator-(int day)//日期-运算 d=d1-90; d1本身不会被修改 而是值传递
{
Date tmp = *this;
return tmp -= day;//+=操作重载
}
//前置++
Date& operator++()//本身改变 可以返回引用
{
return *this += 1;
}
//前置--
Date& operator--()//本身改变 可以返回引用
{
return *this -= 1;
}
//后置++ 与前置++构成重载 参数加入int
Date operator++(int)
{
Date tmp = *this;
*this += 1;
return tmp;
}
//后置-- 与前置--构成重载 参数加入int
Date operator--(int)
{
Date tmp = *this;
*this -= 1;
return tmp;
}
bool operator==(const Date& d)
{
return _y == d._y&&_m == d._m&&_d == d._d;
}
bool operator!=(const Date& d)
{
return !(*this==d);
}
bool operator>(const Date&d)
{
if (_y > d._y)
{
return true;
}
else if (_y == d._y)
{
if (_m > d._m)
return true;
else if (_m == d._m)
{
if (_d > d._d)
{
return true;
}
}
}
return false;
}
bool operator<(const Date& d)
{
return !(*this >= d);
}
bool operator>=(const Date& d)
{
return (*this > d) || (*this == d);
}
bool operator<=(const Date& d)
{
return !(*this >= d);
}
//日期相减 相差天数
int operator-(const Date& d)
{
//小日期经过多少次自加与大日期相同
Date max = *this;
Date min = d;
int flag = 1;
if (max < min)
{
max = d;
min = *this;
flag = -1;
}
int day = 0;
while (min < max)
{
++min;
++day;
}
return flag * day;
}
int getyear()
{
return _y;
}
int getmonth()
{
return _m;
}
int getday()
{
return _d;
}
private:
int _y;
int _m;
int _d;
};
void test()
{
Date d1(2021,2,4);
Date d2(2021, 2, 4);
Date d3(2021, 2, 4);
Date d4(2021, 2, 4);
cout << "当前日期为:" << d1.getyear() << "-" << d1.getmonth() << "-" << d1.getday() << endl;
d1 += 1;
cout << "当前日期后1天为:" << d1.getyear() << "-" << d1.getmonth() << "-" << d1.getday() << endl;
d2 += 30;
cout << "当前日期后30天为:" << d2.getyear() << "-" << d2.getmonth() << "-" << d2.getday() << endl;
d3 += 90;
cout << "当前日期后90天为:" << d3.getyear() << "-" << d3.getmonth() << "-" << d3.getday() << endl;
d4 += 360;
cout << "当前日期后360天为:" << d4.getyear() << "-" << d4.getmonth() << "-" << d4.getday() << endl;
Date d5(2021, 2, 5);
Date d6(2021, 2, 5);
Date d7(2021, 2, 5);
Date d8(2021, 2, 5);
cout << "当前日期为:" << d5.getyear() << "-" << d5.getmonth() << "-" << d5.getday() << endl;
d5 -= 1;
cout << "当前日期前1天为:" << d5.getyear() << "-" << d5.getmonth() << "-" << d5.getday() << endl;
d6 -= 30;
cout << "当前日期前30天为:" << d6.getyear() << "-" << d6.getmonth() << "-" << d6.getday() << endl;
d7 -= 90;
cout << "当前日期前90天为:" << d7.getyear() << "-" << d7.getmonth() << "-" << d7.getday() << endl;
d8 -= 360;
cout << "当前日期前360天为:" << d8.getyear() << "-" << d8.getmonth() << "-" << d8.getday() << endl;
Date d9(2021, 2, 6);
Date d10(2021, 2, 6);
Date d11(2021, 2, 6);
Date d12(2021, 2, 6);
cout << "当前日期为:" << d9.getyear() <<"-"<< d9.getmonth() << "-" << d9.getday() << endl;
//前置++
d10 = ++d9;//d10 与 d9++后 结果保持一致
cout << "当前日期前置增加1天为:" << d10.getyear() << "-" << d10.getmonth() << "-" << d10.getday() << endl;
//后置++
d12 = d11++;//d2 与d11++前结果一致 d11自身加1
cout << "当前日期后置增加1天为:" << d12.getyear() << "-" << d12.getmonth() << "-" << d12.getday() << endl;
Date d13(2020, 1, 6);
Date d14(2021, 2, 6);
cout << "日期:" << d13.getyear() << "-" << d13.getmonth() << "-" << d13.getday() << "与日期:" << d14.getyear() << "-" << d14.getmonth() << "-" << d14.getday() << "相隔天数为:" << d14-d13 << endl;
}
int main()
{
test();
}