0


C++实现日期类

1.日期类局部实现

    **局部实现中的代码只是一部分,不能正常运行。总体代码在最后。(总体代码在win10系统下的vs2019验证)**

(1)类中成员变量

    日期类成员变量应该有:年,月,日。

    代码一:成员变量应设置为 private 权限。
//代码一
class Date {
private:
    int _year;
    int _month;
    int _day;
}

(2)判断输入日期合法函数

    在进行对象的构造时,需要手动传入参数,但需要判断参数的合法性。

    代码二:将每个月的天数设置为数组中的元素,在0下标位置设置占位符,这样从1开始,就可以直接将月份作为下标使用。**(如果日期合法返回true,否则返回false)**
//代码二
bool JudgeDay(int year,int month,int day) {
    if (year < 0)
        return false;

    if (month > 12 || month < 1)
            return false;

    int Days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

        //如果是闰年,二月天数要加一
    if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        Days[2] += 1;

    if (Days[month] >= day && day > 0)
        return true;
    else
        return false;
}

(3)构造函数

    代码三:使用判断函数的返回值作为条件,当日期非法,( **!JudgeDay(year,month,day)** )的值为true,进入条件。
//代码三
Date(int year = 2020,int month = 12,int day = 12) 
    :_year(year)
    ,_month(month)
    ,_day(day)
{
        //当输入的日期不符合实际 JudgeDay返回false,通过取反进入选择语句
    if (!JudgeDay(year,month,day)) {
        _year = 2021;
        _month = 1;
        _day = 2;
    }
}

(4)获取月份对应天数函数

    代码四:
//代码四
int GetDay(int year,int month) {
    int Days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

    if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        Days[2] += 1;

    return Days[month]; 
}

(5)拷贝构造函数

    代码五:
//代码五
Date(const Date& d) 
    :_year(d._year)
    ,_month(d._month)
    ,_day(d._day)
{}

(6)赋值运算符重载

    通过赋值运算符为另一个对象赋值。

    代码六:注意:需要判断是否自己为自己赋值。
//代码六
Date& operator=(const Date& d) {
    //判断是否是自己给自己赋值
    if (this != &d) {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    return *this;
}

(7)+运算符重载

    代码七:+ 运算符重载时需要注意,注意在月份增加到13后要进行更新,年份加1,将月份重新设置为1月份。

    同时,应使用拷贝构造函数构造一个临时变量进行计算,因为不可以改变初始的对象。
//代码七
Date operator+(int day) {
    //此处复用了重载后的 - 
    if (day < 0) {
        return *this - (0 - day);
    }

    Date temp(*this);

    temp._day += day;
    while (temp._day > GetDay(temp._year, temp._month)) {
        //减去本月份应该拥有的天数
        temp._day -= GetDay(temp._year, temp._month);
        //将月份转到下个月
        temp._month += 1;
        if (temp._month > 12) {
            temp._month %= 12;
            temp._year += 1;
        }
    }
    return temp;
}

(8)前置++运算符重载

    代码八:需要符合前置++的运算规则,将本对象加1,然后将本对象返回。
//日期的更新,++
Date& operator++() {
    *this = *this + 1;
    return *this;
}

(9)后置++运算符重载

    代码九:后置++运算规则,用本对象的现有值赋值,然后将本对象加一,所以需要先构造临时对象保存现有值。

   ** 注意:后置++重载时需要加上整型参数。**
//代码九
Date operator++(int x) {
    Date temp(*this);
    *this = *this + 1;
    return temp;
}

(10)-运算符重载

    代码十:重载 - 运算符时,首先需要在循环体内将月份减1,然后进行年份的更新,然后再根据月份更新天数。原因用一个例子解释:

    假设目前是 2022年9月1日,减去30天(**9月30天,8月31天**),正确结果应该是2022年8月2日。那么运行完 ( **temp._day -= day; **) 后,就是2022年9月-29天。如果不先更新月份,而是先加日期(此时加的肯定就是9月的天数),再更新月份,最终结果就是,2022年8月1号。
//代码十
Date operator-(int day) {
    //复用重载后的 + 运算符
    if (day < 0) {
        return *this + (0 - day);
    }

    Date temp(*this);
    temp._day -= day;
    while (temp._day <= 0) {
        temp._month -= 1;

        if (temp._month <= 0) {
            temp._month = 12;
            temp._year -= 1;
        }

        temp._day += GetDay(temp._year, temp._month);
    }
    return temp;
}

(11)前置--运算符重载

    代码十一:和前置++类似
//代码十一
Date& operator--() {
    *this = *this - 1;
    return *this;
}

(12)后置--运算符重载

    代码十二:和后置++类似
//代码十二
Date operator--(int x) {
    Date temp(*this);
    *this = *this - 1;
    return temp;
}

(13)>运算符重载

    代码十三:条件语句中的三个条件使用或运算。

    第一个:左边年份大于右边。第二个:年份相同,左边月份大于右边。第三个:年月相同,左边日期大于右边。
//代码十三
//左边大,返回ture
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;
    }
}

(14)<运算符重载

    代码十四:当( ***this > d || *this == d** ),只要两个条件成立一个,说明左边不小于右边,表达式为false,通过取反,返回true。并且复用了重载后的 > 和 ==
//代码十四:
//复用 > 和 ==
bool operator<(const Date& d) {
    return !(*this > d || *this == d);
}

(15)==运算符重载

    代码十五:三个条件同时成立才相等,返回true
//代码十五
bool operator==(const Date& d) {
    return (_year == d._year) && (_month == d._month) && (_day == d._day);
}

(16)!=运算符重载

    代码十六:复用了重载后的 ==
//代码十六
//复用==
bool operator!=(const Date& d) {
    return !(*this == d);
}

(17)输出运算符(<<)重载

    观察平时如何使用:cout << (要输出的内容) ,有个缺点,只能直接打印内置类型,不能直接打印类类型,可以进行重载。**(注意 cout 也是一个对象,它是ostream的对象)        **

<1>错误重载(重载为类的成员函数)

    重载后的调用机制:cout.operator<<(this)

    但如下的代码有错误,因为 类的成员函数会在第一个参数的位置隐含this指针,所以重载后不符合实际。实际上的操作顺序是 cout << this,重载后顺序 this << cout。这样的话,调用语句就应该是:对象名 << cout。

    代码十七:
//代码十七
ostream& operator<<(ostream& _cout) {
    cout << _year << "-" << _month << "-" << _day;
    return _cout;
}

<2>正确重载(重载为全局函数)

    为了解决上述问题,我们可以将它重载为全局函数,将cout对象的参数放在首位。

    原本的 << 还具有连续输出功能,所以我们需要用一个返回值来完成这个功能,连续调用的机制:举例,cout << a << b。实际上是,( cout.operator<<(a) ) . operator << ( b )。将cout.operator<<(a) 的返回值(cout)再一次作为参数。

    代码十八:这样才是正确重载,但它有一个问题,成员变量已经设置为private,无法在类外直接访问,我们通过友元函数解决,目前只需要知道如何使用友元就好。
//代码十八
ostream& operator<<(ostream & _cout,Date& d) {
    cout << d._year << "-" << d._month << "-" << d._day;
    return _cout;
}
   ** 友元:如果你想让类外函数A使用类B中的全部成员(任何访问权限),就将A设置为B的友元函数。**

    语法:**friend 函数声明**

    代码十九:
//代码十九
class Date {
    friend ostream& operator<<(ostream & _cout,Date& d) ;
private:
    int _year;
    int _month;
    int _day;
}

2.日期类总体实现

#include "iostream"
using namespace std;

class Date {
    friend ostream& operator<<(ostream& _cout, Date& d);
private:
    int _year;
    int _month;
    int _day;
public:
    //构造函数
    Date(int year = 2020,int month = 12,int day = 12) 
        :_year(year)
        ,_month(month)
        ,_day(day)
    {
        //当输入的日期不符合实际 JudgeDay返回false,通过取反进入选择语句
        if (!JudgeDay(year,month,day)) {
            _year = 2021;
            _month = 1;
            _day = 2;
        }
    }

    //判断构造函数中输入的Day变量是否符合实际
    bool JudgeDay(int year,int month,int day) {
        if (year < 0)
            return false;

        if (month > 12 || month < 1)
            return false;

        int Days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

        //如果是闰年,二月天数要加一
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
            Days[2] += 1;

        if (Days[month] >= day && day > 0)
            return true;
        else
            return false;
    }

    //得到对应天数
    int GetDay(int year,int month) {
        int Days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
            Days[2] += 1;
        return Days[month]; 
    }

    //拷贝构造函数
    Date(const Date& d) 
        :_year(d._year)
        ,_month(d._month)
        ,_day(d._day)
    {}

    //赋值运算符重载
    Date& operator=(const Date& d) {
        //判断是否是自己给自己赋值
        if (this != &d) {
            _year = d._year;
            _month = d._month;
            _day = d._day;
        }
        return *this;
    }

    //+运算符重载,计算x天后的日期
    Date operator+(int day) {
        if (day < 0) {
            return *this - (0 - day);
        }

        Date temp(*this);
        temp._day += day;
        while (temp._day > GetDay(temp._year, temp._month)) {
            temp._day -= GetDay(temp._year, temp._month);
            temp._month += 1;
            if (temp._month > 12) {
                temp._month %= 12;
                temp._year += 1;
            }
        }
        return temp;
    }

    //-运算符重载,计算x天前的日期
    Date operator-(int day) {
        //复用重载后的 + 运算符
        if (day < 0) {
            return *this + (0 - day);
        }

        Date temp(*this);
        temp._day -= day;
        while (temp._day <= 0) {
            temp._month -= 1;

            if (temp._month <= 0) {
                temp._month = 12;
                temp._year -= 1;
            }

            temp._day += GetDay(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;
    }

    // >重载
    //this大,返回ture
    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 !(*this > d || *this == d);
    }
    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++() {
        *this = *this + 1;
        return *this;
    }

    //后置++重载
    Date operator++(int x) {
        Date temp(*this);
        *this = *this + 1;
        return temp;
    }

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

    //后置--重载
    Date operator--(int x) {
        Date temp(*this);
        *this = *this - 1;
        return temp;
    }
};
//<<重载为全局函数
ostream& operator<<(ostream & _cout,Date& d) {
    cout << d._year << "-" << d._month << "-" << d._day;
    return _cout;
}

int main() {
    Date d1(2022, 1, 1);
    cout << "d1:" << d1 << endl;//输出 d1:2022-1-1
    Date d2 = d1;
    cout << "d2:" << d2 << endl;//输出 d2:2022-1-1
    Date d3 = d1 - 100;
    cout << "d3:" << d3 << endl;//输出 d3:2021-9-23
    cout << "d3 - d1:" << d3 - d1 << endl;//输出 d3 - d1:100
}
标签: c++

本文转载自: https://blog.csdn.net/weixin_57761086/article/details/126482723
版权归原作者 爱喝酸奶! 所有, 如有侵权,请联系我们删除。

“C++实现日期类”的评论:

还没有评论