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

C++日期类详解 第二级支线任务

日期类的整体

class Date
{
public:// 构造函数Date(int year = 0, int month = 1, int day = 1);// 打印函数void Print() 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);// 日期的大小关系比较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;// 日期-日期int operator-(const Date& d) const;// 析构,拷贝构造,赋值重载可以不写,使用默认生成的即可private:int _year;int _month;int _day;
};

上述代码表示了这次要实现的类,包括了多种运算符的重载,以及构造函数,相似的操作符,我们只实现一个。

日期类的析构和拷贝赋值函数不用写用默认的,因为日期类用的都是内置类型,没有动态开辟的空间,所以不用考虑深拷贝的问题

构造函数

// 获取某年某月的天数
inline int getmonthday(int year, int month)
{// 数组存储平年每个月的天数static int dayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };int day = dayArray[month];if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){//闰年2月的天数day = 29;}return day;
}
// 构造函数
Date::Date(int year, int month, int day)
{// 检查日期的合法性if (year >= 0&& month >= 1 && month <= 12&& day >= 1 && day <= getmonthday(year, month)){_year = year;_month = month;_day = day;}else{// 严格来说抛异常更好cout << "非法日期" << endl;cout << year << "年" << month << "月" << day << "日" << endl;exit(1);}
}

上述代码解析:

一.getmonthday:这个函数用来判断是哪一年的哪一个月有几天

细节:

1.用static或者全局变量开辟dayArray[13],好处在于:节省每次调用函数时重复制造dayArray[13]。

2.inline内联函数,因为在Date对象进行++ -- 还有构造函数等多个函数都要用到getmonthday,所以用内联在调用的地方直接展开,省去了调用函数时找地址的时间消耗。

二.构造函数:构造函数很简单,但对于日期而言,每个月没有32天,没有13月,所以在构造函数要对传入的参数进行审批。错了以后直接exit退出。


operator+=和operator-=

为什么二者要一起讲,因为可以二者可以复用。

+=

// 日期+=天数
Date& Date::operator+=(int day)
{if (day<0){// 复用operator-=*this -= -day;}else{_day += day;// 日期不合法,通过不断调整,直到最后日期合法为止while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month > 12){_year++;_month = 1;}}}return *this;
}

对于上述代码:为什么负数时我们复用-=,因为负数时,我们的日期是减法,但是在加等的逻辑中我们只考虑通过加法去改变日期,所以只考虑日期超限制的情况,如果减法倒退超过限制,我们不用单独写逻辑,而是直接复用-=的逻辑即可。

-= 

// 日期-=天数
Date& Date::operator-=(int day)
{if (day < 0){// 复用operator+=*this += -day;}else{_day -= day;// 日期不合法,通过不断调整,直到最后日期合法为止while (_day <= 0){_month--;if (_month == 0){_year--;_month = 12;}_day += GetMonthDay(_year, _month);}}return *this;
}

 对于上述代码:和+= 相同,-=只考虑下限不考虑上限。所以负数时复用+=。

 记住:减法考虑下限,加法考虑上限,负数考虑复用

operator+

// 日期+天数
Date Date::operator+(int day) const
{Date tmp(*this);// 拷贝构造tmp,用于返回// 复用operator+=tmp += day;return tmp;
}

对于上述代码:

1.我们复用了+= 。

2.为什么要用拷贝构造:参考int 时的加法;如果只是单纯的+1那对i并不影响,而如果是将i + 1赋值给i 那才会对 i 造成影响。所以拷贝构造出一份新的对象,返回这个新对象。而不是在原对象上更改

int i = 0;
i+1;
i = i + 1;

operator- 和 + 同理。 

前置++和后置++

和内置类型一样,前置++返回的是修改后的内容,后置++修改值,但是返回的是没++的内容。

前置++

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

可以看到我们之间返回了*this,并且直接更改的*this。 

后置++

// 后置++
Date Date::operator++(int)
{Date tmp(*this);// 拷贝构造tmp,用于返回// 复用operator+=*this += 1;return tmp;
}

后置++因为我们要返回的值是修改前的,所以我们拷贝构造后返回tmp,但不能引用!!!局部变量后续会销毁,但是传值传出去的是复制体,所以要用传值返回

前置--和后置--同理。

比较运算符

operator==

这里以==为例,其他的符号只是逻辑不同但是代码是类似的。

但值得一提的有:>= 可以复用 operator> 和 operator==. <= 同理。

bool Date::operator==(const Date& d) const
{return _year == d._year&&_month == d._month&&_day == d._day;
}

把该判断的都判断了就对了。

日期-日期

日期类的计算难点就在于,日期的进位,但是对于日期相减是有一个取巧的方法滴。

日期-日期,算天数,我们可以找到较大的日期,然后用较小的日期一直+1,直到 == 较大的日期。中间在用一个变量一直计算+了多少个1.就可以实现了。

// 日期-日期
int Date::operator-(const Date& d) const
{Date max = *this;// 假设第一个日期较大Date min = d;// 假设第二个日期较小int flag = 1;// 此时结果应该为正值if (*this < d){// 假设错误,更正max = d;min = *this;flag = -1;// 此时结果应该为负值}int n = 0;// 记录所加的总天数while (min != max){min++;// 较小的日期++n++;// 总天数++}return n*flag;
}


http://www.mrgr.cn/news/31148.html

相关文章:

  • python-24-一篇文章彻底掌握Python HTTP库Requests
  • LeetCode【0026】删除有序数组中的重复项
  • 谁会从新技术中受益?
  • 【支付行业-支付系统架构及总结】
  • 【Vue】Vue3.0(二十四)Vue3.0中$refs 、$parent 的概念和使用场景
  • 高德地图多个图片组成标点(自定义点标记内容)
  • FB FC里调用全局变量注意事项
  • 用 JS 实现一个发布订阅模式
  • Unity的Text组件中实现输入内容的渐变色效果
  • FedOV
  • solana项目counter,测试过程中执行报错记录分享
  • 【leetcode】堆习题
  • 铲屎官进!宠物空气净化器真的有用吗?哪款去浮毛效果好
  • SQLAlchemy思维导图
  • [产品管理-28]:NPDP新产品开发 - 26 - 产品生命周期管理 - 产品上市的八大步骤
  • 软考高级第四版备考---第四十八天(项目基本要素-项目内外部运行环境、组织系统、项目管理和产品管理)
  • java踩坑
  • Highcharts甘特图基本用法(highcharts-gantt.js)
  • 什么是机房IP?有什么缺点
  • 骨传导耳机哪个牌子比较好?2024耳机排行榜首发!一文读懂谁更值得入手!
  • 虚拟机(VMware)安装,保姆级教程(附所有安装包及所有安装步骤)
  • 稳了,搭建Docker国内源图文教程
  • 微服务架构---Ribbon\Feign
  • 牛客BC68,X型图案
  • 【JS】path的使用说明
  • STM32G474RE使用SPI1中断发送和接收8位数据