• 日期类及其基本功能的实现


    目录

    一 获取月份天数

    二 构造函数

    1 全缺省构造函数

    2 拷贝构造函数

    三 析构函数

    四 运算符重载

    1 > >= < <= == !=

    2 赋值运算符的重载

    3 += 与+

     4 -=与-

    5 前置++与后置++ 前置--与后置--

     6 重载- 实现两个日期相减返回相差的天数


    一 获取月份天数

    获取月份天数采用了静态数组的方式。由于数组下标是从0开始的,为了使月份与下标一一对应,开13个int大小的数组。但是下标为0的位置随便存入一个0,用来占位。之后表示出对应月份对应的天数。

    如果是闰年的话,那么这一年的月份还要+1;

    由于他被频繁调用,所以我把他写在函数的内部,当做内联函数来提高效率。

    1. int GetMonthDay(int year, int month)
    2. {
    3. int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    4. if (year % 400 == 0 || year % 4 == 0 && year % 100 != 0)
    5. {
    6. monthday[2] += 1;
    7. }
    8. return monthday[month];
    9. }

    二 构造函数

    1 全缺省构造函数

    全缺省构造函数其实就是在写构造函数的时候,给年月日都定下对应的缺省值。

    1. Date(int year = 1, int month = 1, int day = 1)
    2. {
    3. _year = year;
    4. _month = month;
    5. _day = day;
    6. }//全缺省构造函数

    2 拷贝构造函数

    拷贝构造函数传入对应的日期类。注意必须要传入引用。否则会产生无穷递归。

    1. Date(Date const& date)
    2. {
    3. _year = date._year;
    4. _month = date._month;
    5. _day = date._day;
    6. }//拷贝构造函数

    三 析构函数

    日期类的析构函数可有可无。因为日期类并没有对应的资源需要清理。但是即使这样,我们不写,编译器也会自动生成一个析构函数。只不过这个析构函数什么事情都不需要做。但是它确确实实被调用了。

    1. ~Date()
    2. {
    3. }//析构函数

    四 运算符重载

    1 > >= < <= == !=

    运算符重载的话,其实只用实现==和<或者==和>即可。因为其他的运算符重载去复用写好的就可以实现了。比如实现<=,那么逻辑上就是>的逻辑取反并且满足==。

    1. bool operator==(const Date& date)const
    2. {
    3. return _year == date._year
    4. && _month == date._month
    5. && _day == date._day;
    6. }
    7. bool operator!=(const Date& date)const
    8. {
    9. return !(*this == date);
    10. }
    11. bool operator>(const Date& date)const
    12. {
    13. if (_year > date._year)
    14. {
    15. return true;
    16. }
    17. else if (_year == date._year && _month > date._month)
    18. {
    19. return true;
    20. }
    21. else if (_year == date._year && _month == date._month && _day > date._day)
    22. {
    23. return true;
    24. }
    25. else
    26. {
    27. return false;
    28. }
    29. }
    30. bool operator>=(const Date& date)const
    31. {
    32. return(*this > date && *this == date);
    33. }
    34. bool operator<(const Date& date)const
    35. {
    36. return !(*this >= date);
    37. }
    38. bool operator<=(const Date& date)const
    39. {
    40. return (*this < date && *this == date);
    41. }

    2 赋值运算符的重载

    赋值运算符的重载可以使用引用传参,并且由于不需要对传入的参数做修改,因此可以用const来修饰。由于返回的是被赋值重载后的*this。不会被销毁。因此也可以用引用返回来提高效率。

    1. Date& operator=(const Date& date)
    2. {
    3. _year = date._year;
    4. _month = date._month;
    5. _day = date._day;
    6. return *this;
    7. }//赋值重载

    3 += 与+

    ①+=思路是进位。首先全部加在日上面,再去进位。进位的规则:如果日期不合法,比如日大于当月的最大天数,那么就需要向月份上面进位。如果月份也大于这一年中的最大月份。那么就向年来进位。

    注意的是,当月份向年进位的时候,同时月份也会被置成1.

    1. Date&operator+=(int day)
    2. {
    3. if (day < 0)
    4. {
    5. return *this -= -day;
    6. }
    7. _day += day;
    8. while(_day > GetMonthDay(_year, _month))
    9. {
    10. _day -= GetMonthDay(_year, _month);
    11. _month+=1;
    12. if (_month > 12)
    13. {
    14. _year += 1;
    15. _month = 1;
    16. }
    17. }
    18. return *this;
    19. }

    ②+

    由于+的话,不会对*this产生修改,因此需要用一个临时变量来完成上述的操作,并且返回这个临时变量。

    其他代码的实现也可以直接复用

    1. Date operator+(int day)
    2. {
    3. Date ret(*this);
    4. ret += day;
    5. return ret;
    6. }

     4 -=与-

    ①-=

    与+=的思路相反。不过要注意的是,需要先判断月份是否合法,再把借到的上一个月的天数加到当月。否则,如果是一月份不合法,借位,借到的就是0月的天数了。

    1. Date& operator-=(int day)
    2. {
    3. if (day < 0)
    4. {
    5. return *this += -day;
    6. }
    7. _day -= day;
    8. while (_day<1)
    9. {
    10. _month -= 1;
    11. if (_month < 1)
    12. {
    13. _year -= 1;
    14. _month = 12;
    15. }
    16. _day += GetMonthDay(_year, _month);//要先判断 因为是借上一年的 如果不判断的话 1月份的天数是负数的情况此时借位加不上去 还需要向年借
    17. }
    18. return *this;
    19. }

    ②-

    和上述一样去复用即可。

     

    1. Date operator-(int day)
    2. {
    3. Date ret(*this);
    4. return ret -= day;
    5. }

    为什么用-=和+=来复用-和+?

    如果反着来的话,需要实现很多次拷贝构造,会降低效率。

    5 前置++与后置++ 前置--与后置--

    ①前置++

    前置++返回的是++前的值,并且本身也会被修改。因此需要用临时变量保存++前的值,并且返回这个临时变量。因此返回值不能用引用。前置++参数列表带int可以不传参,主要是为了与后置++相区分

    1. Date operator++(int)
    2. {
    3. Date ret(*this);
    4. *this += 1;
    5. return ret;
    6. }

    ②后置++

    后置++返回++之后的值,因此直接返回即可。

     

    1. Date& operator++()
    2. {
    3. return *this +=1;
    4. }

    前置--与后置--逻辑和上述的实现差不多。

    不做过多的阐述了。

    1. Date& operator--()
    2. {
    3. return *this -= 1;
    4. }
    5. Date operator--(int)
    6. {
    7. Date ret(*this);
    8. *this -= 1;
    9. return ret;
    10. }

     6 重载- 实现两个日期相减返回相差的天数

    思路:主要是得出二者较小的天数的日期,用计数器来计算两者之间的相差天数。

    flag是为了实现正负。默认第一个日期类型比第二个日期类型要大。flag为正。但是如果与猜想相反的话,大小日期和flag都需要重置。

    1. int operator-( const Date&date)const
    2. {
    3. int flag = 1;
    4. Date min = date;
    5. Date max = *this;
    6. if (*this >date)
    7. {
    8. max = date;
    9. min = *this;
    10. flag = -1;
    11. }
    12. int count = 0;
    13. while (min != max)
    14. {
    15. count++;
    16. min++;
    17. }
    18. return count * flag;
    19. }

     

  • 相关阅读:
    盲人使用公共设施:科技助力无障碍出行与智能识别
    Windows 常用快捷键
    【多线程】探索Java中的多线程编程
    Git学习笔记
    包含Uniapp单聊思路,单群聊集群
    linux驱动34:tasklet小任务机制
    帮扶、提振、担当,第六届土巴兔718全民家装节的新价值和意义
    C++保姆级入门教程(10)—— 一维数组练习
    TEngine框架的导入与运行
    前端教程-rollup
  • 原文地址:https://blog.csdn.net/zhengyawen666/article/details/126023222