IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++详解实现日期类的运算(默认成员函数的综合运用) -> 正文阅读

[C++知识库]C++详解实现日期类的运算(默认成员函数的综合运用)

1.头文件

要点:
(1)声明成员函数与成员变量

(2)针对Date类,构造函数需要自己写,系统不会进行处理,析构函数、拷贝构造函数与赋值重载可以不用写

(3)构造函数的声明与函数,缺省值只能写一处,下面代码中,构造函数的缺省值已经存在,则在函数中不能再存在

(4)前置++与后置++的声明不一样,后置++会多一个int形参,这个形参没有作用,只是为了区分

(5)运算符重载的&:参考拷贝构造函数中的讲解要点

#include<iostream>

using namespace std;

class Date
{
public:
	//构造函数需要写,针对内置类型,会成随机数
	//析构函数、拷贝构造不用写,默认生成就行

	//函数的声明
	Date(int year = 0, int month = 1, int day = 1);

	void Print()
	{
		cout << _year << "年" << _month << "月" << _day << "日";
		cout << endl;
	}

	//日期+=天数
	Date& operator+=(int day);

	//日期 + 天数
	Date operator+(int day);

	// 日期-天数
	Date operator-(int day);

	// 日期-=天数
	Date& operator-=(int day);

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

	// 后置++  会加一个形参,没有意义,只是为了区分前置++
	Date operator++(int);

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

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

	// >运算符重载
	bool operator>(const Date& d);

	// ==运算符重载
	bool operator==(const Date& d);

	// >=运算符重载
	inline bool operator >= (const Date& d);

	// <运算符重载
	bool operator < (const Date& d);

	// <=运算符重载
	bool operator <= (const Date& d);

	// !=运算符重载
	bool operator != (const Date& d);

	// 日期-日期 返回天数
	int operator-(const Date& d);
private:
	int _year;
	int _month;
	int _day;
};

2.函数源文件

要点:
(1)每个月天数的存储:利用一个静态数组存储,每次出了函数,静态数组仍然存在,要调用时直接在静态存储区取,不用每次建立,提高效率

(2)判断闰年时的月份天数,先判断是否是2月,再判断是否是闰年,会提高不少效率

(3)把获取天数的函数设为一个内联函数,也能提高不少效率,获取天数是每次都会调用的,设为内联函数,提高速度

(4)此处的构造函数形参没有缺省值,与头文件中的构造函数有缺省值相对应

(5)检查日期的合法性,day <= GetMonthDay(year, month) 才合法

(6)日期+天数:
operator+=:进位,加上后所给的day值改变了
①加上后超过本月天数,月份+1
②若月份加上后大于12,则进位,年份+1,且月份置为1
另外:要考虑所给的day < 0的情况
operator+:加上后所给的day值不变
复用operator+=代码时,要创建一个新的对象来相加
(operator-= 与operator-情况与上面一致,只是operator-=是借位,减去的是上一个月的天数)

(7)前置++与后置++区别:返回值不一样,前置++返回++之后的值,后置++返回++之前的值

(8)运算符重载:写出operator>与operator==后,其余利用代码复用

(9)日期-日期 返回天数:不能直接相减
①假设一大一小,再比较,若比较与假设不一致,再交换值
②设立flag = 1,是不知道哪个值大或者小,最后可以化解出现负数的情况
③利用min与max不相等,逐渐相加,直到相等,因为中间会出现不同月份的天数,不好一个月一个月的相加

#include"date.h"

inline int GetMonthDay(int  year, int month)
{
	//数组存储每个月的天数
	static int dayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	int day = dayArray[month];

	//判断闰年且是2月
	if (((month == 2) && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	{
		day = 29;
	}
	return day;
}

//缺省值在函数声明时已经给了,此处不再给出,两处地方只能存在一处
Date::Date(int year, int month, int day)
{
	//检查日期的合法性
	if (year >= 0 
		&& month > 0 && month < 13
		&& day > 0 && day <= GetMonthDay(year, month))
	{
		_year = year;
		_month = month;
		_day = day;
	}
	else
	{
		//严格来说,抛异常更好
		cout << "非法日期" << endl;
		cout << year << "年" << month << "月" << day << "日" << endl;
		//assert(false);
	}

}

//日期 + 天数
//若超过本月的天数,则和-本月的天数   月份+1
//若月份大于12,年数+1, 月份置为1
//直到天数合法为止

//日期+天数
Date& Date::operator+=(int day)
{
	if (day < 0)
	{
		*this -= -day;   //减一个负数,相当于加上一个正数
	}
	else
	{
		_day += day;
		//判断天数合法,不合法则进行循环
		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);   //减去当月的天数
			++_month;
			if (_month > 12)
			{
				++_year;
				_month = 1;
			}
		}
	}
	
	return *this;    //返回自己的天数
}

//日期 + 天数    日期本身是没变的
//利用上面+=代码的复用
Date Date::operator+(int day)
{
	Date ret(*this);   //创建一个对象另外来相加
	ret += day;
	return ret;
}

//日期-天数
//不合法,借本月的前一月的天数
// 日期-=天数
Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		//_day += -day;
		判断天数合法,不合法则进行循环
		//while (_day > GetMonthDay(_year, _month))
		//{
		//	_day -= GetMonthDay(_year, _month);   //减去当月的天数
		//	++_month;
		//	if (_month > 12)
		//	{
		//		++_year;
		//		_month = 1;
		//	}
		//}

		//复用,利用上面+=的函数
		*this += -day;    //负数-负数=正数
	}
	else
	{
		_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;    //tmp.operator-=(&tmp.day)
 	return tmp;
}


//前置++与后置++的区别:返回值不一样,前置++返回的是相加之后的值,后置++返回的是相加之前的值
// 前置++   
Date& Date::operator++()
{
	*this += 1;
	return *this;   //因为返回的值是没有消失的,直接可以用引用
}

// 后置++
Date Date::operator++(int)
{
	//返回的是相加之前的值,所以要创建一个对象保存
	Date ret = *this;
	*this += 1;
	return ret;
}

//和++一样
// 后置--
Date Date::operator--(int)
{
	Date ret = *this;
	*this -= 1;
	return ret;
}

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

// >运算符重载  d1 > d2   ->  d1.operator>(&d1,d2)
bool Date::operator>(const Date& d)
{
	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)
{
	return _year == d._year && _month == d._month && _day == d._day;
}

// >=运算符重载
inline bool Date::operator >= (const Date& d)
{
	return  *this > d || *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);
}

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

	int n = 0;  //计算min到max的之间差值
	while (min != max)
	{
		++min;
		++n;
	}

	return n * flag;   //如果n为负数,flag为-1,n为正数,flag为1
}

3.测试源文件

#include"date.h"

//检验日期合法性
void test1()
{
	Date d1(2021, 5, 25);
	d1.Print();

	Date d2(2021, 0, 0);
	//d2.Print();

	Date d3(2021, 2, 29);
	d3.Print();
}
//测试:日期 + / += 天数
void test2()
{
	Date d1(2021, 5, 25);
	d1.Print();

	d1 += 7;
	d1.Print();

	Date d2 = d1 + 100;  //d1本身是没有变,创建一个对象来接收
	d2.Print();
}
//测试 :日期 - / -= 天数
void test3()
{
	Date d1(2021, 5, 27);
	d1.Print();

	d1 -= 100;
	d1.Print();

	Date d2(2021, 5, 27);
	d2 -= -100;
	d2.Print();
}

//测试前置++    后置++
void test4()
{
	Date d1(2021, 5, 27);
	d1.Print();  //5.27
	
	++d1;
	d1.Print();  //5.28

	Date ret1 = d1++;
	d1.Print();   //5.29    调用的是++这个函数,this指针传给了d1,导致d1实现了++
	ret1.Print();   //5.28   返回值,还没有+1
}

//测试前置--   后置--
void test5()
{
	Date d1(2021, 5, 27);
	d1.Print();    //5.27

	--d1;
	d1.Print();   //  5.26

	Date ret2 = d1--;
	d1.Print();    //5.25
	ret2.Print();   //5.26
}

//测试日期-日期
void test6()
{
	Date d1(2021, 5, 27);
	Date d2(2021, 12, 31);

	cout << d1 - d2 << endl;
	cout << d2 - d1 << endl;
}
int main()
{
	//test1();
	//test2();
	//test3();
	//test4();
	//test5();
	test6();
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-23 10:32:07  更:2021-07-23 10:34:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/29 0:50:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码