【C++】日期类

        使用C++的知识点,练习一个日期类。


        

class Date
{
public:
    
    //构造函数
    Date(int year=1,int month=1,int day=1)
        :_year(year)
        ,_month(month)
        ,_day(day)
    {
        assert(CheckDate());
    }
    
    //拷贝构造函数    
    Date(const Date& d)
    {
        _year=d._year;
        _month=d._month;
        _day=d._day;
    }

    void Print()
	{
		printf("%d年,%d月,%d日\n", _year, _month, _day);
	}


private:
    int _year;
    int _month;
    int _day;
};

        构造函数设置了缺省值,变成默认构造函数,这里设置缺省值的时候还是要注意,日期肯定没有0月0日的,所以这里设置为了1。

        

//获取月份的天数
void GetMonthDay(int year,int month)
{
    static int days[13]={0,31,30,31,30,31,30,31,31,30,31,30,31};

    
    if(month==2 && (year%4==0 && year%100!=0 || year&400==0)){
        return 29;
    }
    
    return days[month];

}


//检查日期是否正确 比如 2022,7,32
bool CheckDate()
{
    if(_year>=1
      && _month>0 && month<13
      && _day>0  && _day<GetMonth(_year,_month)        
    )
    {
        return true;
    }    
    else
    {
        return false;
    }

}

        检查月份的时候要检查一下闰年,如果是闰年二月有29天。

        

重载运算符

//日期加天数,天数超过一个月,进一月。超过一年进一年。
Date& operator+=(int day)
{
    if( day < 0 ){
            
        return *this -= -day;     //这里是防止输入 d += -100 的情况
    }

    _day += day;
    
    while(_day > GetMonthDay(_year,_month)){
        
        _day -= GetMonthDay(_year,_month);
        
        _month++;
        if(_month == 13){
            _year++;
            _month = 1;
        }
        
    }

    return *this;
    

}

//日期减天数,超过一个月则后退一个月,超出一年后退一年。
Date& operator-=(int day)
{
    
        if( day < 0 ){
            
            return *this += -day;     //这里是防止输入 d -= -100 的情况
        }
        
        _day -= day;
        while(_day <= 0){
            
            _month--;
            
            if(_month == 0){
                _month=1;
                _year--;
            }
            
            _day += GetMonthDay(_year,_month);         
        
        }

    
        return *this;
}

       

        这里刚开始的里面的if判断相互复用了,但是不会构成死循环,就是你调用我然后我再调用你的情况,运算符重载里面很多复用的情况,所以要避免相互调用的情况。

//前置--  减后返回可以用引用
Date& operator--()
{
    return *this -= 1;
}

//后置--  先返回后相减  
Date operator--(int)
{
	Date temp = *this; //使用临时变量记录之前的值,所以这里不能返回引用
	*this -= 1;
	return temp;
}

Date& operator++()
{
	return *this += 1;
}

Date operator++(int)
{
	Date temp = *this;
	*this += 1;
	return temp;
}

       

        这里要注意前置和后置的区分,用括号里面的int来区分的,有int则是后置。

        然后要后置的意义是先返回后计算,所以用了一个临时变量来记录修改之前的值,所以这里不能返回引用,不然临时变量出函数销毁。

        

//重载赋值符号
Date& operator=(const Date& d)
{
    if(this!=&d) //这里的& 是取地址的意思
    {
        _year=d._year;
        _month=d._month;
        _day=d._day;
    }

    return *this;

}

       

        这里重载了赋值符号,要注意库里面的赋值符号是可以自己赋值给自己的,所以这里要判断一下,自己赋值自己遇到就跳过。

        然后库里面的赋值是可以连续赋值的,所以这里就要返回对象的引用

        然后这里有个深浅拷贝的问题,但是这里类里面全是内置类型,所以使用浅拷贝也可以。

//比较符号的重载
bool operator>(const Date& d)
{
    if((_year > d._year)
        || (_year == d._year && _month > d._month)
        || (_year == d._year && _month == d._month && _day > d._day)
        )
    {
        return true;
    }
    else
    {
        return false;
    }
}

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


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);
}
	
	
bool operator<(const Date& d)
{
    
    return !(*this>=d);
}

          任何一个类只需要写一个>,和==重载(或者<  ==) 剩下的比较运算符复用即可。但是要注意相互调用造成死循环的情况。

        

//日期减日期  获取相差的天数
int operator-(const Date& d)
{
    int flag=1;
    Date max=*this;
    Date min=d;
    
    if(*this<d){    //这里复用了小于号
        
        max=d;
        min=*this;
        flag=-1;
    }

    
    int n=0;
    while(max!=min){  //这里复用了不等于符号
        
        min++;
        n++;
    }
        
    return n*flag;

}


//函数重载 + 运算符重载 日期减天数
Date operator-(int day)
{
    Date temp=*this;
    temp -= day;    //这里复用了减等于
    return temp;
}


//重载加号不能改变对象本身
Date operator+(int day)
{
	//直接复用+=
	Date ret = *this;
	ret += day;
	return ret;
}

        这里对减号重载了两次,分别对应不同参数的情况。

        而且加号和减号跟加等于减等于不一样,其不会改变对象本身的值,这里就要使用一个临时变量返回,所以返回值不能用引用。

//重载流插入 流提取  ">>"、"<<"
friend ostream& operator<<(ostream& out,const Date& d);
	

//注意这要修改d的值,所以不能设置用const修饰,不然会报错
friend istream& operator>>(istream& in, Date& d);



ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "/" << d._month << "/" << d._day << endl;
	return out;
}


istream& operator>>(istream& in, Date& d)
{
	in >> d._year >> d._month >> d._day;
	assert(d.CheckDate());        //检查输入的日期是否正确
	return in;
}

        这里的函数如果重载在类内部,使用的时候是 d<<cout ,实际上cout平时使用的时候是在左边的,所以这里要在类外面重载,然后为了能再类外部使用到类的私有变量,所以设置函数为友元函数。
        并且为了能连续的打印和提取这里要返回流插入、流提取的引用。


        这里要一个简易的日期类就完成了,但是要注意考虑现实一点的因素,比如运算符的重载要有意义,比如一个日期加上一个日期,是没意义的所以不用写。

        然后就是在历史上有几天是被删除了的,所以太长的日期相减也是会出错误的,还有就是闰年并不是在公元元年被定义出来的,是过了后面好久。所以计算闰年的方法可能也要判断一下,这里只是练习C++的初步使用,所以不考虑太多。

猜你喜欢

转载自blog.csdn.net/weixin_45423515/article/details/126573848