C++运算符重载之 日期类

学完运算符重载和友元函数,我们就应该学会运用这些函数,而写一个日期类的代码基本包含了运算符重载的大部分东西。
接下来就看一看这个日期类的到底该怎么写。
首先,简单接介绍一下这个日期类的基本功能:

// 当前日期days天后是什么日期? 
Date operator+(int days); 
// 当前日期days天前是什么日期? 
Date operator-(int days); 
// 两个日期之间差了多少天? 
int operator-(const Date& d); 
// 日期比大小 
bool operator>(const Date& d); 
bool operator<(const Date& d); 
bool operator==(const Date& d); 
bool operator!=(const Date& d); 
Date& operator=(const Date& d); 
// 重载取地址符号 
Date* operator&(); 
// 前置++ 
Date& operator++(); 
// 后置++ 
Date operator++(int); 
// 前置-- 
Date& operator--(); 
// 后置++ 
Date operator--(int); 

下面是代码实现,代码比较长,请耐心看完,在代码中我作了详细的解释,有什么疑问可以留言联系。

#include <iostream>
using namespace std;

class Date
{
public:
    Date()
    {}
    Date(int year,int month,int day)
        :_year(year)
        , _month(month)
        , _day(day)
    {
        if (!(year > 0 && (month > 0 && month < 13) && day>0 && day < GetMonthDays(year, month)))
        {
            cout << "日期非法!" << endl;
        }
    }
    // 当前日期days天后是什么日期? 
    Date operator+(int days)
    {
        if (days < 0)
        {
            return (*this) - (0 - days);  //如果要加上的数为负数的处理办法,就让当前对象减去这个负数
        }
        int DaysInMonth = 0;
        Date temp(*this);
        temp._day += days;
        while (temp._day >(DaysInMonth = GetMonthDays(temp._year, temp._month)))   //检测加完之后的日期是否合法
        {
            temp._day -= DaysInMonth;
            temp._month++;
            if (temp._month > 12)
            {
                temp._year += 1;
                temp._month = 1;
            }
        }
        return temp;
    }

    //// 当前日期days天前是什么日期? 
    Date operator-(int days)
    {
        if (days < 0)
        {
            return *this + (0 - days);    //如果要减上的数为负数的处理办法,就让当前对象加上这个负数
        }
        Date temp(*this);
        temp._day -= days;
        while (temp._day <= 0)
        {
            temp._month -= 1;
            if (0 == temp._month)
            {
                temp._year -= 1;
                temp._month = 12;
            }
            temp._day += GetMonthDays(temp._year, temp._month);
        }
        return temp;
    }

    // 两个日期之间差了多少天? 
    int operator-(const Date& d)
    {
        Date minDate(*this);
        Date maxDate(d);
        if (minDate > maxDate)
        {
            minDate = d;
            maxDate = *this;
        }
        int count = 0;
        while (minDate != maxDate)
        {
            count++;
            ++minDate;
        }
        return count;
    }


    // 日期比大小 
    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;
        }
        return false;
    }
    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);
    }

    //为了实现连续赋值,因此要有返回值,为了效率高,因此给引用
    Date& operator=(const Date& d)
    {
        if (this != &d)  //检测是不是自己给自己赋值
        {
            _year = d._year;
            _month = d._month;
            _day = d._day;
        }
        return *this;
    }

    // 重载取地址符号 
    Date* operator&()
    {
        return this;
    }

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

    // 后置++ ,返回的是保存之前的旧值
    Date operator++(int)
    {
        Date temp(*this);
        _day += 1;
        return temp;
    }

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

    // 后置-- 
    Date operator--(int)
    {
        Date temp(*this);
        _day -= 1;
        return temp;
    }   
    friend ostream& operator<<(ostream& _cout, const Date& d)
    {
        _cout << d._year << "/" << d._month << "/" << d._day;
        return _cout;
    }
    bool IsLeapyYear(int year)  //判断是不是闰年
    {
        if ((0 == year % 4 && 0 != year % 100) || (0 == year % 400))
            return true;
        else
            return false;
    }
private:     
    int GetMonthDays(int year, int month)
    {
        int DayOfMonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  //每个月的天数
        //先判断是不是二月
        if (2 == month && IsLeapyYear(year))
        {
            DayOfMonth[month] += 1;
        }
        return DayOfMonth[month];
    }
    //日期类的析构函数没有任何作用,因此这里不用给出析构函数,因为当前对象并没有管理任何资源
private:
    int _year;
    int _month;
    int _day;
};

void TestDate()
{
    Date d1(2018, 8, 4);
    Date d2;
    d2 = d1;
    d2 = d1 + 100;
    cout << d2 << endl;
}

//现在我们假设一个场景:假如现在我们想要知道100天以后是几号,那么我们应该怎么做呢?
int main()
{
    TestDate();
    //我们可能会想到在这个日期类直接加上100不就好了,事实真是这样么?显然,编译报错了(这里自己上机实验),说明这样做是不可取的。
    //d1+100;
    //下面的代码是边完善日期类写的测试,感兴趣可以自己上机实验
#if 0
    Date d1(2018, 8, 4);
    Date d2(d1);
    d2.PrintDate();
    Date d3(2018, 8, 5);
    Date& d4 = d1;
    d3++;
    ++d3;
    d2 = d1;    // 这句话可以理解为 d2.operator=(d1);====> Date::operator=(&d2,&d1)
    d2 = d1 + 100;
#endif
    return 0;
}

这里给出部分检测结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_39412582/article/details/81412089