C++日期类的实现

这里我们把类的声明放在.h 文件里面,实现放在.cpp文件,这样做的原因是,我们在类里面实现的函数,编译器都会当做内联函数处理的,我们把类的一些成员函数的声明和实现分开,是为了把一些不适合当内联函数给区分开来。

 

有些成员函数是不会修改到值的,我们都可以加上const修饰,以做到保护代码的作用,防止乱写,我们把const加在声明后面是对隐藏的this指针修饰的。

// >运算符重载 const加在括号外是对隐藏的this指针修饰的
bool operator>(const Date& d)const;
// >运算符重载 const加在括号外是对隐藏的this指针修饰的
bool Date::operator>(const Date& d)const
  {
      if(_year > d._year)
      {
          return true;
      }
      else if(_year == d._year && _month > d._month)
      {
          return true;
      }
      else if(_year == d._year && _month == d._month && _day > d._day)
      {
          return true;
      }
      return false;
  }
日期类的实现
题目内容:
class Date

{

public:

// 获取某年某月的天数

int GetMonthDay(int year, int month);



  // 全缺省的构造函数

Date(int year = 1900, int month = 1, int day = 1);



  // 拷贝构造函数

// d2(d1)

Date(const Date& d);

   

  // 赋值运算符重载

// d2 = d3 -> d2.operator=(&d2, d3)

Date& operator=(const Date& d);



  // 析构函数

~Date();



  // 日期+=天数

Date& operator+=(int day);



  // 日期+天数

Date operator+(int day);



  // 日期-天数

Date operator-(int day);



   // 日期-=天数

Date& operator-=(int day);



  // 前置++

Date& operator++();



  // 后置++

Date operator++(int);



  // 后置--

Date operator--(int);



  // 前置--

Date& operator--();



  // >运算符重载

bool operator>(const Date& d);



  // ==运算符重载

bool operator==(const Date& d);



  // >=运算符重载

bool operator >= (const Date& d);

   

  // <运算符重载

bool operator < (const Date& d);



   // <=运算符重载

bool operator <= (const Date& d);



  // !=运算符重载

bool operator != (const Date& d);



  // 日期-日期 返回天数

int operator-(const Date& d);

private:

int _year;

int _month;

int _day;

};

我们需要先实现一个,可以通过年,月,获取到当个月的天数的函数,以便我们后期一些函数的实现。

    // 获取某年某月的天数
    int GetMonthDay(int year, int month)
    {
        static int days[]= {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31};
        int day = days[month];
        if (month == 2 &&((year % 4 == 0 && year % 100 != 0) || (year%400 == 0)))
        {
            day += 1;
        }
        return day;
    }

这里我们把一年中的每个月的天数用一个数组保存起来,由于数组是0开始的,为了方便我们后面获取天数时,不用加1处理,我们把第一个数置0,后面开始保存我们每个月的天数,当然还要考虑到润年时2月要加1。

    // 全缺省的构造函数
    Date(int year = 2022, int month = 9, int day = 22)
    {
        _year = year;
        _month = month;
        _day = day;
        // 我们需要考虑到年份,月份,天数是否合法,需要做个处理,如果非法要打印出来提示
        if(!(year >= 1 &&
           (month >=1 && month <=12)&&
           GetMonthDay(year, month) >= day))
        {
            std::cout<< "非法" << std::endl;
        }

    }

接下来是我们的全缺省构造函数,构造函数是调用比较频繁的,我们把他放在类里面,凡是在类里面的函数,编译器都会把他当成内联函数处理。

    // 拷贝构造函数
    // d2(d1)
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }

由于时间类的成员都是内置类型的,我们也可以不写拷贝构造函数,编译器默认生成的,也可以用,那些是需要我们自己写拷贝构造函数呢,例如涉及到内存管理的时候就需要。

// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
//由于我们把赋值运算符声明和实现分开了,所以我们需要在函数名前加上域运算符,以便编译器能找到
Date& Date::operator=(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
    return *this;
}

赋值函数的原型实际为,Date& operator=(Date* this,const Date& d) 隐藏了一个this指针

时间类的成员都是内置类型即int,char,之类的,我们也可以直接用编译器默认生成的赋值运算符重载,这里我们自己写出来是为了更多理解,赋值是把已经创建好的两个类,把右值给左值重新初始化,两个类是出了函数还存在的,所以我们用引用,并且我们是不会更改右值的,所以我们加上const修饰,为什么要返回一个类呢,是因为我们赋值的话,有可能遇到 d0 = d1 = d2;连续赋值,所以一般是返回左值的。

  ~Date()
    {
      _year = 0;
      _month = 0;
      _day = 0;
    }

时间类的成员都是内置类型即int,char,之类的,我们也可以直接用编译器默认生成的析构函数,这里我们自己写出来是为了更多理解。

    // 日期+=天数
Date& Date::operator+=(int day)
{

    if(day < 0)
    {
        return *this -= -day;
    }
    _day +=day;
    while(_day > GetMonthDay(_year, _month))
    {
        _day-= GetMonthDay(_year, _month);
        ++_month;
        if(_month == 13)
        {
            _month =1;
            ++_year;
        }
    }
    //返回+=后的结果是为了 连续的+=情况的处理 d0 += d1 += d2;
    return *this;
}

日期加等上一个天数之后的日期,是会改变自身的,如果加上的天数是一个负的,我们直接复用-=运算符重载函数,反之,则直接加上这个天数,通过跟当前的年,月的天数对比,如果大于,则月份加1,如果月份等于13了则年份加1,月份重置为1,一直循环到天数不大于当前的年,月的天数。

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

日期加天数后的日期,不会改变自身,所以我们可以创建一个临时变量,进行+=运算符重载函数的复用,返回之后的值即可,注意这里返回不能加引用,由于返回的值出了函数就销毁了,所以不能加引用。

// 日期-天数
Date Date::operator-(int day)
{
    Date ret(*this);
    ret -= day;
    return ret;
}

日期减天数,不会改变自身,我们可以复用-=运算符重载函数,创建一个临时变量,进行-=后返回即可,注意这里返回不能加引用,由于返回的值出了函数就销毁了,所以不能加引用。

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

日期减等日期的,跟日期加等日期的,很相似,只不过把+改为-,++改为--,就可以了。

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

日期的前置++,复用+=函数,返回即可,由于++的值出了函数后还在,所以可以在返回值上加引用。

// 后置++ 比前置多了一个参数,是为了区分前置++
Date Date::operator++(int)
{
    Date tmp(*this);
    *this += 1;
    return tmp;
}

前置++,跟后置++都是一样的++,所以编译器为了区分他们,做了规定,后置++,要多加个形参,我们调用的时候不需要传参,编译器自己会传参。

日期的后置++,需要创建一个临时变量返回,然后再复用+=函数,改变自身的值,由于后置++比前置++,要多创建一个临时变量,所以能前置就前置。

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

前置--跟前置++一样的。

// 后置-- 需要多加个形参,编译器规定,为了区分前置和后置
Date Date::operator--(int)
{
    Date tmp(*this);
    *this -= 1;
    return tmp; 
}

后置--跟后置--一样的。

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

判断一个日期是否,大于另外一个日期,这里需要先判断年份,如果年份一样,则判断月份,如果月份一样,则判断天数。

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

判断一个日期是否等于另外一个日期,我们需要依次判断,全部符合才为真,否则为假。

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

判断一个日期是否大于等于另外一个日期,这里可以复用上面的大于,和等于函数,这里大于为真,等于也为真,其中一个为真则返回真。

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

判断一个日期是否小于另外一个日期,我们也是复用到大于和等于函数,只不过对结果取反,如果大于为真,取反后为假,等于也是一样的。

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

判断一个日期是否小于等于另外一个日期,我们也是利用到小于和等于函数。

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

判断一个日期不等于另外一个日期,如果年月日,其中一个不等于结果则为真,否则为假。

// 日期-日期 返回天数
int Date::operator-(const Date& d)
{
    //这里调用到拷贝构造函数
    Date max = *this;
    //这里调用到拷贝构造函数
    Date min = d;
    //如果左值大于右值,则结果为正的,反之则为负的
    int flag = 1;
    //这里调用到<运算符重载
    if(max < d)
    {
        //这里调用到赋值函数
        max = d;
        //这里调用到赋值函数
        min = *this;
        //如果左值大于右值,则结果为正的,反之则为负的
        flag = -1;
    }
    int count = 0;
    //这里调用到!=函数重载
    while(max != min)
    {
        //这里调用到++函数重载
        ++min;
        //count变量是为了记录,小的日期++几次到大的日期,最后就是他们的差值
        ++count;
    }
    return count*flag;
}

日期减日期,返回差值的天数,这里复用到很多我们之前写的函数重载,我们通过把两个日期把最大的日期,赋值给max,另外一个赋值给min,最后通过一个循环,记录min++几次等于max的时候循环结束,count变量则记录了,min++几次到max的,flag是为了区分结果是正的还是负的。

Date.cpp文件的代码


#pragma once
#include "Date.hpp"

Date& Date::operator+=(int day)
{

    if(day < 0)
    {
        return *this -= -day;
    }
    _day +=day;
    while(_day > GetMonthDay(_year, _month))
    {
        _day-= GetMonthDay(_year, _month);
        ++_month;
        if(_month == 13)
        {
            _month =1;
            ++_year;
        }
    }
    return *this;
}

bool Date::operator>(const Date& d)const
  {
      if(_year > d._year)
      {
          return true;
      }
      else if(_year == d._year && _month > d._month)
      {
          return true;
      }
      else if(_year == d._year && _month == d._month && _day > d._day)
      {
          return true;
      }
      return false;
  }
// !=运算符重载
bool Date::operator != (const Date& d)const
{
    if(_year != d._year ||_month != d._month || _day != d._day)
    {
        return true;
    }
    return false;
}
// 日期-=天数
Date& Date::operator-=(int day)
{
    if(day < 0)
    {
        return *this += -day;
    }
    _day -=day;
    while(_day <= 0)
    {
        --_month;
        if(_month == 0)
        {
            _month =12;
            --_year;
        }
        _day+= GetMonthDay(_year, _month); 
    }
    return *this;
}

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

// ==运算符重载
bool Date::operator==(const Date& d)const
{
  return _year == d._year &&_month == d._month &&_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 || *this == d);
}

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

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

// 后置++ 比前置多了一个参数,是为了区分前置++
Date Date::operator++(int)
{
    Date tmp(*this);
    *this += 1;
    return tmp;
}

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

// 日期-日期 返回天数
int Date::operator-(const Date& d)const
{
    //这里调用到拷贝构造函数
    Date max = *this;
    //这里调用到拷贝构造函数
    Date min = d;
    //如果左值大于右值,则结果为正的,反之则为负的
    int flag = 1;
    //这里调用到<运算符重载
    if(max < d)
    {
        //这里调用到赋值函数
        max = d;
        //这里调用到赋值函数
        min = *this;
        //如果左值大于右值,则结果为正的,反之则为负的
        flag = -1;
    }
    int count = 0;
    //这里调用到!=函数重载
    while(max != min)
    {
        //这里调用到++函数重载
        ++min;
        //count变量是为了记录,小的日期++几次到大的日期,最后就是他们的差值
        ++count;
    }
    return count*flag;
}

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

Date.hpp的代码


#pragma once

#include <iostream>
using namespace std;

class Date
{
    friend ostream& operator<<(ostream& out,const Date& d);
public:
    // 获取某年某月的天数
    int GetMonthDay(int year, int month)
    {
        static int days[]= {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31};
        int day = days[month];
        if (month == 2 &&((year % 4 == 0 && year % 100 != 0) || (year%400 == 0)))
        {
            day += 1;
        }
        return day;
    }

    // 全缺省的构造函数
    Date(int year = 2022, int month = 9, int day = 22)
    {
        if(year >= 1 &&
           (month >=1 && month <=12)&&
           GetMonthDay(year, month) >= day)
        {
            _year = year;
            _month = month;
            _day = day;
        }
        else
        {
            std::cout<< "非法" << std::endl;
        }
    }
    // 拷贝构造函数
    // d2(d1)
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
     
    // 赋值运算符重载
  // d2 = d3 -> d2.operator=(&d2, d3)
    Date& operator=(const Date& d);
    // 析构函数
  ~Date()
    {
      _year = 0;
      _month = 0;
      _day = 0;
    }

    // 日期+=天数
    Date& operator+=(int day);
    
    void print()
    {
        std::cout << _year << "/" << _month << "/" << _day << std::endl;
    }
    
    // 日期+天数
  Date operator+(int day)const
    {
      Date ret(*this);
      ret += day;
      return ret;
    }

    // 日期-天数
    Date operator-(int day)const;

     // 日期-=天数
  Date& operator-=(int day);

    // 前置++
  Date& operator++();

    // 后置++
  Date operator++(int);

    // 后置--
  Date operator--(int);
    // 前置--
  Date& operator--();

    // >运算符重载
    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 ostream& operator<<(ostream& out,const Date& d)
{
    out<< d._year << "/" << d._month << "/" << d._day << endl;
    return out;
}

main.cpp的代码

通过调用Date类实现一个简易版本的日期计算器

​
void memu()
{
    cout << "************************************************" << endl;
    cout << "***** 1.日期减日期           2. 日期加天数     *****" << endl;
    cout << "***** 3.日期比大小           4. 日期减天数     *****" << endl;
    cout << "***** 0.退出计算器           -----------     *****" << endl;
    cout << "************************************************" << endl;
}

int main()
{
    Date d1,d2;
    int chose = 0;
    int day = 0;
    do
    {
        memu();
        cout << "请选择你要的计算方式:"<<endl;
        cin >> chose;
        switch(chose)
        {
            case 1:
                cout<< "请输入日期,年月日间需加空格,以回车键结束"<<endl;
                cin >> d1 >> d2;
                cout<<d1-d2<<"天"<<endl;
                break;
            case 2:
                cout<< "请输入日期,年月日间需加空格,以回车键结束"<<endl;
                cin >> d1 >> day;
                cout << d1 - day << endl;
                break;
            case 3:
                cout<< "请输入日期,年月日间需加空格,以回车键结束"<<endl;
                cin >> d1 >> d2;
                cout << (d1 > d2) << endl;
                break;
            case 4:
                cout<< "请输入日期,年月日间需加空格,以回车键结束"<<endl;
                cin >> d1 >> day;
                cout << d1 + day << endl;
                break;
            case 0:
                cout<< "退出成功" <<endl;
                break;
            default :
                cout << "输入错误 请重新输入" <<endl;
        }
    }while(chose);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值