c++日期类(Date类)

1.Date中的构造函数

构造函数的作用可以说是对类变量的初始化(Init)如果我们不写构造函数,系统会生成默认的构造函数,但是对于date类来说,这里的默认构造函数什么都不做,如果你创建了一个 Date d1,系统调用了默认构造函数,你会发现这里的年月日都是随机值,我们为了让d1在初始化的时候就有一个确认的日期,所以得自己动手写一个全缺省的构造函数

我们在函数声明中给一个确定的值,让每个创建出来的日期类变量都有一个默认的初始值 1900,1,1


2.Date中的析构函数

析构函数的作用同构造函数是对应的,这里是销毁某些特定的成员变量,如我们用malloc申请出来的内存,如果不在析构函数中做特定的操作,就很可能导致内存泄漏,不过在Date中的成员并不需要特殊的去释放他,他们生长在栈上,会随函数栈桢的结束自动释放掉,所以这里就可以使用默认的析构函数,我们可以不用书写

3.Date中的拷贝构造函数

创建对象的时候使用同类对象初始化,拷贝构造函数其实是一个构造函数的重载,如果我们没有实现拷贝构造函数,系统也会自动生成拷贝构造函数,来依次拷贝类成员进行初始化

需要注意:拷贝构造函数必须使用传引用的方式返回,否则会造成无穷递归

4.Date中的运算符重载

这里我实现了如下几个运算符的重载


需要注意的是

1.当返回一个Date类的变量时,我们使用传值返回( 例如 + )还是传引用返回(例如 +=)?

        可以这么说,所有需要返回一个Date类的函数都可以使用传值返回,可是传值返回在返回的过程中会生成一个临时变量,并且会调用一次构造函数,开销比较大,所以在可以使用传引用返回的情况下,我们最好有限考虑传引用返回。

        传引用返回的条件是,你要返回的Date变量在出了当前函数作用域还存在(例如 静态变量static,或者是传值传进来的变量),只要生命周期大于这个函数的周期,就可以返回引用。当然还需要考虑这个变量应不应该被改变,例如使用 d1 + 1 的时候,d1是不需要被改变的,所以返回的值只可以是在类里面创建的变量。使用 d1 += 1的时候,d1的值会被改变掉,所以就可以直接返回改变以后的d1

2.为了提高我们写代码的效率,我们可以复用自己写过的运算符

        例如,我们已经写好了一个 ' < '的运算符,当我们需要些 ‘ >= ’的时候就可以直接使用 ‘ !< ’,这样写不仅仅可以提高我们写代码的效率,还可以提高我们修改代码的效率,如果你有100函数都是用的相同逻辑,调用的是一个基础的函数,如果这个逻辑出错,修改的时候就只需要该基础函数的逻辑

3.区分前置++(--)和后置++(--)

        相同点:两者的运算符都是 ++,所以易于混淆

        不同点:因为本身难以区分,所以编译器帮了我们很大的忙,在调用++(--)运算符时,编译器当然可以辨别程序员输入的是前置还是后置,如果是后置,编译器在传参的时候就会传一个 int 类型的变量,在调用的时候如果发现什么参数都没有,那就默认是前置++(--),如果发现参数中有一个 int 类型的形参,那么就会处理成后置的++(--),但是这里的 int形参什么事情都不做,只是为了区分前置和后置

下面我们看一下完整代码:

//Date.h
#pragma once

class Date
{
public:
    Date(int year = 1900,int month = 1,int day = 1);
    ~Date(){}
    bool IsValid();
    int GetMonthDay(int year,int month);
    bool IsLeapYear(int year);
    void Show();

    Date& 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);
    bool operator<(const Date& d);
    Date operator+(int day);
    Date& operator+=(int day);
    Date operator-(int day);
    Date& operator-=(int day);
    int operator-(const Date& d);//日期-日期 返回天数
    Date& operator++();//默认前置
    Date operator++(int);//用参数标志后置++
    Date& operator--();
    Date operator--(int);

private:
    int _year;
    int _month;
    int _day;
};
//date.cpp
#include "date.h"
#include <iostream>
#include <assert.h>
using namespace std;

Date::Date(int year,int month,int day):_year(year),_month(month),_day(day)
{
    if(!IsValid())  // -> this.IsValid()
    {
        assert(false);
    }
}

bool Date::IsValid()
{
    return (_year > 0 
       && _month > 0 && _month <= 12 
       &&_day > 0 && _day <= GetMonthDay(_year,_month));
}

int Date::GetMonthDay(int year,int month)
{
    int arr[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    if(month == 2 && IsLeapYear(year))
    {
        ++arr[2];
    }
    return arr[month];
}

bool Date::IsLeapYear(int year)
{
    return ((year % 4 == 0 && year % 100 != 0)
        || year % 400 == 0);
}

void Date::Show()
{
    cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}

//  运算符重载经历以下几个步骤
//  (d1==d2)
//  d1.operator==(d2)
//  d1.operator==(&d1,d2)
//  bool Date::operator==(Date* this,const Date& d)
bool Date::operator==(const Date& d)
{
    if(_year == d._year && _month == d._month && _day == d._day)
        return true;
    return false;
}

//传值返回:会多调用一次拷贝构造函数
//传引用返回:直接返回,不需要调用拷贝构造
//            出了作用于变量还在,尽量使用传引用返回
Date& Date::operator=(const Date& d)
{
    if(this != &d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    return *this;
}

bool Date::operator>=(const Date& d)
{
    return !(*this < d);
}

bool Date::operator<=(const Date& d)
{
    return ((*this < d) || (*this == d));
}
bool Date::operator!=(const Date& d)
{
    return !(*this == d);
}

bool Date::operator>(const Date& d)
{
    return !(*this <= d);
}

bool Date::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;
}

Date Date::operator+(int day)
{
    if(day < 0)
    {
        return (*this) - (-day);
    }
    Date d(*this);
    d._day += day;
    while(d.IsValid() == false)
    {
        int month_day = GetMonthDay(d._year,d._month);
        d._day -= month_day;
        ++d._month;
        if(d._month > 12)
        {
            d._month = 1;
            ++d._year;
        }
    }
    return d;
}

Date& Date::operator+=(int day)
{
    *this = (*this + day);
    return *this;
}

Date Date::operator-(int day)
{
    if(day < 0)
    {
        return (*this) + (-day);
    }
    Date d(*this);
    d._day -= day;
    while(d.IsValid() == false)
    {
        --d._month;
        if(d._month == 0)
        {
            --d._year;
            d._month = 12;
        }
        int pre_month_day = GetMonthDay(d._year,d._month);
        d._day += pre_month_day;
    }
    return d;
}

Date& Date::operator-=(int day)
{
    *this = (*this - day);
    return *this;
}

int Date::operator-(const Date& d)//日期-日期 返回天数
{
    int flag = 1;
    Date max = (*this);
    Date min = d;
    if((*this) < d)
    {
        max = d;
        min = (*this);
        flag = -1;
    }
    int count = 0;
    while(max != min)
    {
        ++min;
        ++count;
    }
    return flag*count;
}

//  ++d1 ->  d1.operator++(&d1);
Date& Date::operator++()//默认前置
{
    *this += 1; // 只调用一个函数
    //*this = *this + 1; //调用两个函数,还要调用拷贝构造函数
    return *this;
}

//  d1++ ->  d1.operator++(&d1,0);
Date Date::operator++(int)//用参数标志后置++
{
    Date tmp(*this);
    *this += 1;
    return tmp;
}

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

Date Date::operator--(int)
{
    Date tmp(*this);
    *this -= 1;
    return tmp;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值