当前位置: 首页 > 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.lryc.cn/news/442029.html

相关文章:

  • java--通用启动/停止shell脚本
  • Flutter-底部选择弹窗(showModalBottomSheet)
  • Linux——k8s认识
  • EC Shop安装指南 [ Apache PHP Mysql ]
  • 无线感知会议系列【3】【基于WiFi和4G/5G的非接触无线感知:挑战、理论和应用-1】
  • Virtuoso服务在centos中自动停止的原因分析及解决方案
  • 泽众P-One性能测试平台火焰图帮助定位产品性能问题
  • 数据结构修炼——顺序表和链表的区别与联系
  • AD9854 为什么输出波形幅度受限??
  • 在grafana上配置显示全部node资源信息概览
  • MySQL —— 索引
  • (已解决)vscode如何选择python解释器
  • sql刷题常用函数
  • Golang | Leetcode Golang题解之第417题太平洋大西洋水流问题
  • Acwing Hash表
  • 大健康裂变分销小程序开发
  • js取出一个对象中指定的字段(封装公共方法)
  • 【黑马点评】已解决java.lang.NullPointerException异常
  • 计算机专业的就业方向
  • VSCode C++ Tasks.json中的变量
  • 第一次安装Pytorch
  • Python数据分析-Steam 收入排名前 1500 的游戏
  • Android14请求动态申请存储权限
  • Doris:数据库建表最佳实践
  • Parallels Desktop 20(Mac虚拟机) v20.0.0 for Mac 最新破解版(支持M系列)
  • 【已解决】华为AR100-S路由器 恢复出厂后,找不到5G wifi的设置
  • 【MongoDB】--MongoDB批量操作
  • 数据库常规操作
  • 基于STM32设计的水渠闸门远程控制系统(华为云IOT)(226)
  • 鸿蒙开发(NEXT/API 12)【响应校验】远场通信服务