C++日期类实现

我们在学习完类与对象,具备了写一些类的能力

所以,在这篇文章我将详细讲解日期类如何去实现。用到的知识点也会在讲解一下

修饰符:public、private

public是公用的,并且可以放置我们的成员函数,成员函数就是去完成一些功能

private是私有的,就是我们一些重要的数据不能去随便修改的变量,把放置在private里面保护起来,放置在private的变量我们叫成员变量

cpp 复制代码
#include <iostream>
#include <cassert>

using namespace std;

class Date
{
public:
	//public:是公用的,放置成员函数,成员函数是完成一些功能
	//成员函数
	Date(int year = 1, int month = 1, int day = 1);
private:
	//private:是重要的数据不能随便修改,所以使用private去保护他
	//成员变量
	int _year;
	int _month;
	int _day;
};

构造、析构函数

构造函数:构造函数主要是完成初始化工作的

析构函数:析构函数主要是完成清理工作的

我们使用的是全缺省构造函数去初始化,原因是:你不给他初始化他会随机一个值,那就很不靠谱,所以我们使用全缺省构造函数,可以帮助我们自己去控制那个随机值

.h文件

cpp 复制代码
class Date
{
public:
	//public:是公用的,放置成员函数,成员函数是完成一些功能
	//成员函数
	Date(int year = 1, int month = 1, int day = 1);//全缺省构造函数
private:
	//private:是重要的数据不能随便修改,所以使用private去保护他
	//成员变量
	int _year;
	int _month;
	int _day;
};

.c

cpp 复制代码
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

为什么我们在.c没有写带参数呢?其实C++语法规定了

  • 默认参数只能在函数声明中指定(头文件中)

  • 在函数定义中不能重复指定默认参数

  • 这是C++的语法规定

为什么我们没有写析构函数呢?

我们之前说过,析构函数是用来清理空间和资源的,但是前提是,我们申请了空间,才会去写析构函数,但是我们在日期类中并没有去申请空间,所以不用去写析构函数

那大家还记得我们的声明和定义吗?这里就在唠嗑几句

声明:就是做出了口头承诺,实际上行动没有做

定义:就是行动上做出来了

总而言之:我明天借你一百钱,这是声明,呐一百块钱给你了,这是定义

在C++中.c是定义(完成功能、给一百块钱),而.h是声明(准备做功能、明天给你一百块钱)

运算重载符

快速的过一遍,详细去看看我的带小白学习C++类与对象(中)-CSDN博客文章哈

运算重载符

在内置类型中,符号我们可以正常去使用,但是自定义了话,我们使用编译器的,编译器会报错,所以我们要自己写一个运算重载函数,去支持我们的运算符

比较运算符

我们实现一个等于,然后再去复用等于

cpp 复制代码
bool Date::operator==(const Date& d)
{
	return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator!=(const Date& d)
{
	return !(*this == d);
}

复用就是用我们写好的等于这个运算符,然后去用我们的不等于运算符

==就是用我们写好的运算符

最后给出所有的运算符

.h

cpp 复制代码
#include <iostream>
#include <cassert>

using namespace std;

class Date
{
public:
	//public:是公用的,放置成员函数,成员函数是完成一些功能 
	
	//成员函数
	Date(int year = 1, int month = 1, int day = 1);//全缺省构造函数

	void Print();//数据可视化

	//运算重载符
	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);

private:
	//private:是重要的数据不能随便修改,所以使用private去保护他
	//成员变量
	int _year;
	int _month;
	int _day;
};

.c

cpp 复制代码
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)
		{
			return _day > d._day;
		}
	}
	return false;
}
bool Date::operator>=(const Date& d)
{
	return !(*this < d);
}
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)
		{
			return _day < d._day;
		}
	}
	return false;
}
bool Date::operator<=(const Date& d)
{
	return !(*this > d);
}
bool Date::operator==(const Date& d)
{
	return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator!=(const Date& d)
{
	return !(*this == d);
}

+-运算符

先说一下,我们的+,连那个的区别

cpp 复制代码
Date& operator+=(int day);
Date operator+(int day);

第一个

  • 修改自身:直接修改调用对象的日期

  • 返回引用 :返回 Date&,支持链式调用

  • 非const:需要修改对象,所以不能是const

  • 原地操作:在原有对象上修改

例如:

cpp 复制代码
Date d(2024, 5, 1);
d += 10;           // d变成2024-5-11

第二个

  • 不修改自身:创建新对象进行修改

  • 返回副本 :返回 Date(值),不是引用

  • const函数:承诺不修改当前对象

  • 创建新对象:每次调用都产生新对象

例如:

cpp 复制代码
Date d1(2024, 5, 1);
Date d2 = d1 + 10;  // d1不变,d2是2024-5-11
cpp 复制代码
Date& Date::operator+=(int day)
{
	//tmp += 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;
}

去复用他的+=

cpp 复制代码
Date Date::operator+(int day)
{
	Date tmp = *this;
	tmp += day;
	return tmp;
}

GetMonthDay是判断闰年,后面会给出所有的代码,-运算符也同理

最后给出所有的日期类代码

.h

cpp 复制代码
#pragma once

#include <iostream>
#include <cassert>

using namespace std;

class Date
{
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);

public:
	//public:是公用的,放置成员函数,成员函数是完成一些功能 
	
	//成员函数
	bool CheckDate() const;

	Date(int year = 1, int month = 1, int day = 1);//全缺省构造函数

	void Print();//数据可视化

	int GetMonthDay(int year, int month) const
	{
		assert(month > 0 && month < 13);

		static int monthDayArray[13] = { -1, 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 monthDayArray[month];
	}

	//运算重载符
	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) const;
	Date& operator-=(int day);

private:
	//private:是重要的数据不能随便修改,所以使用private去保护他
	//成员变量
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);

.c

cpp 复制代码
#include "Date.h"

bool Date::CheckDate() const
{
	if (_month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month))
	{
		return false;
	}
	return true;
}

Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
	if (!CheckDate())
	{
		cout << "日期非法:";
		Print();
	}
}

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

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

Date& Date::operator+=(int day)
{
	//tmp += 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) const
{
	Date tmp = *this;
	tmp -= day;

	return tmp;
}

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

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

		_day += GetMonthDay(_year, _month);
	}

	return *this;
}

ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

istream& operator>>(istream& in, Date& d)
{
	cout << "请依次输入年月日:>";
	in >> d._year >> d._month >> d._day;
	return in;
}
相关推荐
阿松のblog1 天前
CPP经典题
c++
Jeremy爱编码1 天前
电话号码的字母组合
java·算法·leetcode
月明长歌1 天前
JavaThread类详解核心属性、常用方法与实践
java·开发语言·jvm
kaico20181 天前
JVM的垃圾回收
开发语言·jvm
YuTaoShao1 天前
【LeetCode 每日一题】1339. 分裂二叉树的最大乘积
算法·leetcode·职场和发展
Neil今天也要学习1 天前
永磁同步电机控制算法--基于增量式模型的鲁棒无差拍电流预测控制
单片机·嵌入式硬件·算法
pulinzt1 天前
【python第三节】循环+函数初步
开发语言·python
zfj3211 天前
java垃圾收集 minorgc majargc fullgc
java·开发语言·jvm·gc·垃圾收集器
leoufung1 天前
LeetCode 172. Factorial Trailing Zeroes 题解
算法·leetcode·职场和发展