C++类与对象入门实践(日期类的实现)

7 篇文章 0 订阅

日期类

class Date
{
public:
    //成员函数

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

日期类成员对象:  年、月、日

实现功能:  成员函数

     即用四个默认成员函数就可以实现一个日期类。

1.构造函数

       实现日期年月日的初始化,函数包括年月日的初始化,传参(判断初始化当年是否为闰年,即获得当年2月具体的天数)

//获取某年具体的某一天
inline int GetMonthDay(int year, int month)  //写成内联函数,减少函数调用栈开销
{
    static int MonthDayArray[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};   
    //static 静态,保证数组中的天数不变
    if(month == 2
	&& ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
    {
	return 29;  //实现瑞年2月输出29天
    }
    else
    {
	return MonthDayArray[month];
    }
}
Date(int year = 1900, int month = 1, int day = 1)
{
    if(year >= 1900     //保证日期的合法性
	&& (month > 0 && month <= 13)
	&& day <= GetMonthDay(year, month))
    {
	_year = year;
	_month = month;
	_day = day;
    }
    else
    {
	cout << "非法日期!" << endl;
    }
}

2.析构函数

      日期类的构造中没用开辟新空间,也没有打开文件等操作。因此使用系统的默认析构函数就够用

      不需要自定义实现。

3.拷贝构造函数

      日期类的拷贝构造,只用拷贝对象中的内容,即编译器默认实现的浅拷贝(按字节序依次拷贝)。

      需要注意拷贝日期的const修饰,和函数参数传引用等问题。

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

Date d1(2019, 5, 12);

Date d2;
d2(d1);

4.赋值运算符重载

      函数原型:返回值类型 operator操作符(参数列表)

      在日期类中用来实现:日期加减天数、日期减日期、日期比较赋值等

      运算符重载可以写在全局中,也可写在类里面,一般建议写在类里面。使他们转换为内联函数,减少函数调用栈开销。

1) 日期加天数:实现 +=  就可利用此运算符重载实现 +    ++ 等运算符重载

       思路: 日期+天数,利用循环  用日期的天数加上给定天数、判断日期天数大于本月的应有天数,则给月份加1、月份等于12时,年份加1,月份置为1,直到天数为本月合理天数结束返回。

Date& operator+=(int day)  //函数返回值带引用,表示返回值变量在出了函数作用域还在
{
	if(day < 0)
	{   //日期小于0 则等于-正天数
		return *this -= -day;
	}
	_day += day;  //先把天数加起来
	while(_day > GetMonthDay(_year, _month))  //天数不合理
	{
		if(_month == 12)
		{   //月到12   则年加1
			++_year;
			_month = 1;
		}
		++_month;
		_day -= GetMonthDay(_year, _month);  //天数减去这月正常的天数,再取判断
	}
	return *this;
}

2)日期减天数:实现 -=  就可利用此运算符重载实现 -    -- 等运算符重载

      思路:日期减天天数,日期的天减去天数,循环判断日期天数是否小于等于0,月份减一,如果月份等于0,年份减一,月份置为12月

                 日期天数加上本月的合理天数再去判断。

Date& operator-=(int day)
{
	if(_day < 0)
	{   //数天小于0
		return *this += -day;
	}
	_day -= day;
	while(_day <= 0)  //天数小于等于0进入循环
	{
		--_month;   //月份为1  年份减一
		if(_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

3)日期 - 日期:  返回两个日期相差的天数

      思路:取两个日期变量,表示两个日期。  小日期++,直到等于大日期。用计数器days记录 并返回

int operator-(const Date& d)
{
	Date minDate(*this);
	Date maxDate(d);
	int flag = 1;
	if(minDate > maxDate)
	{
	    maxDate = *this;
	    minDate = d;
            flag = -1;
	}
	int days = 0;
	while(minDate != maxDate)
	{
	    minDate += 1;
	    ++days;
	}
	return days * flag;
}

4) 日期间的比较:  boo类型返回值

       实现 <   > 就可以根据运算符重载对 >取反就可实现 <=    >=   等

bool operator<(const Date& d) const
{
	if((_year < d._year)  //只要有一个小于就小于
		|| (_year == d._year && _month < d._month)
		|| (_year == d._year && _month == d._month && _day < d._day))
	{
		return true;
	}
	else
	{
		return false;
	}
}

日期类具体实现C++代码如下:

  成员函数建议都在写在类里面,默认内联。

    此处的复制运算符重载,为测试程序没有写进类里。

Date.h

#include <iostream>

using std::cout;
using std::endl;

#pragma once

class Date
{
public:
	//构造函数:  初始化对象、函数名与类名相同、无返回值、对象实例化时系统自动调用
	//1.系统默认构造函数(没什么实际作用,自动调用后,初始化的对象还是随机值)
	/*Date()
	{   //无参构造函数
		_year = 1900;
		_month = 1;
		_day = 1;
	}*/
	//2.用户自定义构造函数,通常构造函数还需要能判断日期的有效性
	//Date(int year = 1900, int month = 1, int day = 1)
	//{   //与上面构造函数构成重载,全缺省参数
	//	//一般推荐这种写法
	//	_year = year;
	//	_month = month;
	//	_day = day;
	//}
	//可返回某年某月具体有多少天
	inline int GetMonthDay(int year, int month)
	{
	    static 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)))
	    {   //瑞年的2月是29天
		return 29;
	    }

	    return MonthArray[month];
	}
	Date(int year = 1900, int month = 1, int day = 1)
	{
	    if (year >= 1900
		&& month > 0 && month < 13
		&& day > 0 && day <= GetMonthDay(year, month))
	    {
		_year = year;
		_month = month;
		_day = day;
	    }
	    else
	    {
		cout << "非法输入" << endl;
	    }
	}

	//析构函数: 完成清理:如 malloc -> free   fopen -> fclose
	//1.析构函数名实在类名前加上字符~
	//2.无参数 无返回值
	//3.一个类只有一个析构函数,若未显示定义,系统会自动生成默认的析构函数
	//4.对象生命周期结束时,C++编译系统对自动调用析构函数。
	~Date()
	{   //每次对象结束时,编译系统都会自动调用析构函数
	    cout << "析构函数调用" << endl;
	}


	//拷贝构造函数:创建相同的类对象、对构造函数传引用类型的对象,一般常用const修饰
	//1.拷贝构造函数时=是构造函数的一个重载形式
	//2.他的参数只用一个且必须使用引用传参,如果使用传值形式,会引发无穷递归调用
	//3.没有自定义时,系统自动生成默认的拷贝构造函数(默认按字节序完成拷贝)
	//    值拷贝/或浅拷贝
	Date(const Date& d)
	{
	    _year = d._year;
	    _month = d._month;
	    _day = d._day;
	}


	//赋值运算符重载
	//运算符重载:有特殊函数名的函数
	//函数原型:返回值类型+operator操作符(参数列表)
	//1.不能通过其他符号来创建新的操作符
	//2.重载操作符必须有一个类类型或者枚举类型的操作数
	//3.用于内置类型的操作符,其含义不能改变
	//4.作为类成员函数重载时,其形参看起来少一个,操作符有一个默认的形参this
	//5.  .*  ::   sizeof  ?:  .   五个运算符不能重载
	//运算符重载一般可以写成全局的,但需要成员变量为公有的
	//所以一般还是写在类里面
	bool operator>(const Date& d) const;
	bool operator>=(const Date& d) const;
	bool operator<(const Date& d) const;
	bool operator<=(const Date& d) const;
	bool operator==(const Date& d) const;
	bool operator!=(const Date& d) const;

	Date& operator++();       //前置++
	Date operator++(int);    //后置++

	Date& operator--();       //前置--
	Date operator--(int);    //后置--

	Date operator+(int day) const;      
	Date operator-(int day) const;    

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

	int operator-(const Date& d);

	void Print()
	{
	    cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

Date.cpp

#include "Date.h"

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

    return false;
}
bool Date::operator>=(const Date& d) const
{
    if (*this < d)
    {
	return false;
    }
    else
    {
	return true;
    }
}
bool Date::operator<(const Date& d) const
{
    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 Date::operator<=(const Date& d) const
{
    if (*this > d)
    {
	return false;
    }
    else
    {
	return true;
    }
}
bool Date::operator==(const Date& d) const
{
    return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator!=(const Date& d) const
{
    return _year != d._year || _month != d._month || _day != d._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)
	{
		++_year;
	        _month = 1;
	}
    }

    return *this;
}
Date& Date::operator++()      //前置++
{
    *this += 1;
    return *this;
}
Date Date::operator++(int)   //后置++
{
    Date ret(*this); //拷贝构造
    *this += 1;
    return ret;
}
Date Date::operator+(int day) const
{
    Date ret = *this;
    ret += day;
    return ret;
}


Date& Date::operator--()         //前置--
{
    *this -= 1;
    return *this;
}
Date Date::operator--(int)     //后置--
{
    Date ret(*this);
    ret -= 1;
    return ret;
}
Date Date::operator-(int day) const
{
    Date ret = *this;
    ret -= day;
    return ret;
}
Date& Date::operator-=(int day)
{
    _day -= day;
    while (_day <= 0)
    {
	if (_month == 1)
	{
		_year--;
		_month = 12;
	}
	else
	{
		_month--;
	}
	_day += GetMonthDay(_year, _month);
    }
    return *this;
}

int Date::operator-(const Date& d)  //两个日期相减
{
    Date maxDate(*this);
    Date minDate(d);
    int flag = 1;
    if (maxDate < minDate)
    {
	flag = -1;
	maxDate = d;
	minDate = *this;
    }
    int days = 0;
    while (minDate != maxDate)
    {
	minDate += 1;
	++days;
    }
    return days * flag;
}

main.cpp

#include "Date.h"

//写测试程序
int main()
{
    Date d1(2019, 5, 13);
    d1.Print();

    Date d2;
    d2.Print();

    Date d3(d1);
        d3.Print();

    cout << d3 - d2 << endl;

    d3 += 18;
    d3.Print();
    
    d3 -= 10;
    d3.Print();

    (d2 + 10000).Print();
	

    return 0;
}

 

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值