C++--------时间类的实现


提示:以下是本篇文章正文内容

一、时间类

1.日期的比较(重载运算符)

(1).==

bool operator==(const Date& y);

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

(2).!= 

bool operator!=(const Date& y);

bool Date::operator!=(const Date& y)
{
	return !(*this == y);//复用==,相反就是不等于,后面的我们可以采用复用前面我们写的代码
}

  (3).>

 bool operator>(const Date& y);

bool Date::operator>(const Date& y)
{
	if (_year > y._year)
	{
		return true;
	}
	else if (_year == y._year && _month > y._month)
	{
		return true;
	}
	else if (_year == y._year && _month == y._month && _day > y._day)
	{
		return true;
	}

	return false;
}

   (4).<

    bool operator<(const Date& y);


bool Date::operator<(const Date& y)
{
	return !(*this >= y);//复用>=
}

    (5).>=


    bool operator>=(const Date& y);


bool Date::operator>=(const Date& y)
{
	return *this > y || *this == y;
}

     (6).<=


    bool operator<=(const Date& y);

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

(2)日期的加减

   (1)-

int operator-(const Date& d);

int Date::operator-(const Date& d)//两个日期相减,我们可以用最小的那个日期不断加一天,直到等于最大的那个日期就停止。while控制循环,n就是它们之间相差的天数。flag用来标记如果小的日期减大的日期就是-,大的减小的就是+
{
	// 假设左大右小
	int flag = 1;
	Date max = *this;
	Date min = d;

	// 假设错了,左小右大
	if (*this < d)
	{
		max = d;
		min = *this;
		flag = -1;
	}

	int n = 0;
	while (min != max)
	{
		++min;//复用++,Date& Date::operator++()
		++n;//累加的天数
	}

	return n * flag;
}


    (2)+=

Date& operator+=(int day);

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)//如果月份=13,就年++
		{
			_year++;
			_month = 1;
		}
	}

	return *this;
}

//Date& Date::operator+=(int day)//我们不建议这种方式虽然复用+,不过它要拷贝3次对象,*this+day中有2次,然后返回的对象又赋值给*this又一次,效率比较低
//{
//	//Date d = *this + day;//拷贝构造
//	//*this = d;
//
//	*this = *this + day;
//	return *this;
//}


    (3)+

Date operator+(int day);

Date Date::operator+(int day)//,拷贝2次对象,返回值临时对象拷贝一次,拷贝对象一次
{
	Date tmp(*this);//+不改变对象自己,所以拷贝一个和自己相同对象
	tmp += day;

	return tmp; 
}

//方式2
//Date Date::operator+(int day)//拷贝2次对象
//{
//	Date tmp(*this);
//
//	tmp._day += day;
//	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
//	{
//		tmp._day -= GetMonthDay(tmp._year, tmp._month);
//
//		++tmp._month;
//
//		if (tmp._month == 13)
//		{
//			tmp._year++;
//			tmp._month = 1;
//		}
//	}
//
//	return tmp;
//}


   (4)-=

Date& operator-=(int day);

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

	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}

		_day += GetMonthDay(_year, _month);//获取月份(在下面的Date.c中定义)
	}

	return *this;
}


    (5)-

Date operator-(int day)

Date Date::operator-(int day)
{
	Date tmp(*this);
	tmp -= day;

	return tmp;
}

   (6)前缀++

Date& operator++();

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


    (7)后置++

Date operator++(int);

Date Date::operator++(int)//C++为了不和前置++,冲突,参数有个类型int
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

   (8)前置--

Date& operator--();

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


    (9)后置--

Date operator--(int);

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

	return tmp;
}

(3)重载输入输出<<和>>

  1. ostream& operator<<(ostream& out, const Date& d);


   2. istream& operator>>(istream& in, Date& d);

这里的输入输出重载,是全局函数不是该类的成员函数,只是把它声明为该类的友元函数。这里我们为什么不可以重载为成员函数呢?

因为如果是成员函数,它会有隐藏的this指针,会占据参数的第一个位置,使用的时候感觉怪怪的
  


//这里的输入输出重载,是全局函数不是该类的成员函数,只是把它声明为该类的友元函数(需要在类里面申明)。
    friend ostream& operator<<(ostream& out, const Date& d);
    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;

	return in;
}

二、时间类代码

1.Date.h

#include<iostream>
#include<assert.h>
using namespace std;

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1);//构造函数,数据类型是内置类型,我们可以不写析构函数,编译器会在最后调用默认生成的析构函数

    void Print();
    int GetMonthDay(int year, int month);//获取月份的天数

    bool operator==(const Date& y);
    bool operator!=(const Date& y);
    bool operator>(const Date& y);
    bool operator<(const Date& y);
    bool operator>=(const Date& y);
    bool operator<=(const Date& y);

    int operator-(const Date& d);
    Date& operator+=(int day);
    Date operator+(int day);
    Date& operator-=(int day);
    Date operator-(int day);

    Date& operator++();
    Date operator++(int);

    Date& operator--();
    Date operator--(int);
private:
    int _year;
    int _month;
    int _day;
};

2.Date.c

#include "Date.h"

Date::Date(int year, int month, int day)
{
    _year = year;
    _month = month;
    _day = day;

    if (_year < 1 ||
        _month < 1 || _month > 12 ||
        _day < 1 || _day > GetMonthDay(_year, _month))
    {
        //assert(false);
        Print();
        cout << "日期非法" << endl;
    }
}

void Date::Print()
{
    cout << _year << "/" << _month << "/" << _day << endl;
}

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

// d1 != d2
bool Date::operator!=(const Date& y)
{
    return !(*this == y);
}

bool Date::operator>(const Date& y)
{
    if (_year > y._year)
    {
        return true;
    }
    else if (_year == y._year && _month > y._month)
    {
        return true;
    }
    else if (_year == y._year && _month == y._month && _day > y._day)
    {
        return true;
    }

    return false;
}

bool Date::operator>=(const Date& y)
{
    return *this > y || *this == y;
}

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

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

int Date::GetMonthDay(int year, int month)
{
    assert(year >= 1 && month >= 1 && month <= 12);

    int monthArray[13] = { 0, 31, 28, 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 monthArray[month];
}

// d1 += 100
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)
        {
            _year++;
            _month = 1;
        }
    }

    return *this;
}

Date Date::operator+(int day)
{
    Date tmp(*this);
    tmp += day;

    return tmp;
}
 

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

    _day -= day;
    while (_day <= 0)
    {
        --_month;
        if (_month == 0)
        {
            --_year;
            _month = 12;
        }

        _day += GetMonthDay(_year, _month);
    }

    return *this;
}

Date Date::operator-(int day)
{
    Date tmp(*this);
    tmp -= day;

    return tmp;
}


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

// d1++
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;
}

// d1 - d2
int Date::operator-(const Date& d)
{
    // 假设左大右小,保证max是日期大的那个,min是小的那个
    int flag = 1;//标记
    Date max = *this;
    Date min = d;

    // 假设错了,左小右大
    if (*this < d)
    {
        max = d;
        min = *this;
        flag = -1;
    }

    int n = 0;
    while (min != max)
    {
        ++min;
        ++n;
    }

    return n * flag;
}

3.test.c

#include "Date.h"

void TestDate1()
{
    Date d1(2023, 10, 24);
    d1.Print();

    Date ret1 = d1 - 100;
    ret1.Print();

    Date ret2 = d1 - 10000;
    ret2.Print();

    Date ret3 = d1 + 100;
    ret3.Print();

    Date ret4 = d1 + 10000;
    ret4.Print();
}

void TestDate2()
{
    Date d1(2023, 10, 24);
    d1.Print();

    ++d1;
    d1.operator++();
    d1.Print();

    d1++;
    d1.operator++(10);
    d1.operator++(1);
    d1.Print();
}

void TestDate3()
{
    Date d1(2023, 10, 24);
    d1.Print();

    
    Date d2(2024, 5, 5);
    d2.Print()
 

    cout << d2 - d1 << endl;
 

}

void TestDate4()
{
    Date d1(2023, 10, 24);
    d1 += -100;

    d1.Print();
}

int main()
{
    TestDate3();

    return 0;
}


总结

在写类的时候,我们尽量把相同的代码放在一起,同时我们分别把申明和源代码分开写在不同文件中,方便管理。为简化代码,我们可以考虑代码的复用,要注意的是复用的时候,可以考虑一下比较优化的复用,比如复用+=,方式二,拷贝对象有三次就不选择,如果是链表的话,加起来太多了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值