从自定义日期类角度解析运算符重载,友元函数(friend)

发布于:2025-08-31 ⋅ 阅读:(25) ⋅ 点赞:(0)

运算符重载

Date.h

  首先定义我们的日期类。在日期类中深入理解+,+= ,-,-=,<,<=,>,>=,==,!=,++,-- 。

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

class Date {
public:
	Date(int year, int month, int day);
	void print() const;
	Date(const Date&d);
	int GetYear() {
		return _year;
	}
	int GetMonth() {
		return _month;
	}
	int GetDay() {
		return _day;
	}
private:
	int _year;
	int _month;
	int _day;
};

Data.cpp

  在Data.cpp中声明函数。

#include"Date.h"

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

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

Date::Date(const Date& d) {
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

在后续板块中,第一部分的代码放在Date.h中,第二部分的代码放在Date.cpp中。
在日期中为了快速获得某年某月的天数,需要在Date.h中写一个函数获取具体的天数。

更新Date.h

在Date.h中写入GetMonthDay()函数,用于获取某年某月的天数,在类里面写入的成员函数默认是inline修饰的内联函数。生命周期和函数的生命周期一样。

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

class Date {
public:
	Date(int year, int month, int day);
	void print() const;
	Date(const Date&d);
	//默认是inline
//用inline修饰的函数叫内联函数,可以提高编程效率
int GetMonthDay(int year, int month) {
	//此数组需要频繁的调用,放入静态区
	//静态区的生命周期和程序的生命周期一样
	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;
	}
	else {
		return MonthDayArray[month];
	}
	
}
	int GetYear() {
		return _year;
	}
	int GetMonth() {
		return _month;
	}
	int GetDay() {
		return _day;
	}
private:
	int _year;
	int _month;
	int _day;
};

重载+,+=(日期+/+=天数)

  重载+,想要知道一个日期加上day天后的是什么日期,原有的日期不变。
  重载+=,想知道一个日期加上day天后原有的日期会变成什么日期,原有的日期需要改变。

Date operator+(int day) const;
//返回引用(Date&)直接操作原对象,无额外拷贝开销。
Date& operator+=(int day);

  要明白日期加天数日期本身是不会变化的。所以在(+)重载中不能改变原有的日期。

Date Date::operator+(int day) const {
	//日期加天数  原有的日期不变需要进行创建临时this
	Date tmp = *this;
	//+=进行了赋值重载
	tmp += day;
	return tmp;
}

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

	while (_day > GetMonthDay(_year, _month)) {
		_day -= GetMonthDay(_year, _month);
		if (_month > (_month + 1)%12 ) {
			_year++;
		}
		_month = (_month + 1) % 12;
	}

	return *this; //返回当前对象的引用
}

重载-,-=(日期-/-=天数)

  重载-,想要知道一个日期减上day天后的是什么日期,原有的日期不变。
  重载-=,想知道一个日期减上day天后原有的日期会变成什么日期,原有的日期需要改变。

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

  要明白日期j减天数日期本身是不会变化的。所以在(-)重载中不能改变原有的日期。

Date Date::operator-(int day) const {
	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) {
			_month = 12;
			_year--;
		}
		_day += GetMonthDay(_year,_month);
	}
	return *this;
	
}

重载 <,<=,>,>=,==,!= (日期 比较 日期)

  在以下的重载中,写出两个,便可以推出其余重载。
  进行对两个日期的对比。

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;
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) {
			return _day < d._day;
		}
	}
	return false;
}

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

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

重载 前置++和后置++ (++日期或日期++)

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

重载 -(日期-日期)

int operator-(const Date& d);
int Date:: operator-(const Date& d) {
	Date max = *this;
	Date min = d;
	int flag = 1;
	if (max < min) {
		swap(max, min);
		flag = -1;
	}
	int cnt = 0;
	while (max != min) {
		++min;
		cnt++;
	}
	return cnt * flag; 
}

重载流插入

  这样重载依旧符合用户习惯。

ostream& operator<<(ostream& out, const Date& d);
ostream& operator<<(ostream& out, const Date& d) {
	//out就是cout
	out << d._year << "-" << d._month << "-" << d._day << endl;
	return out;
}

重载流提取

//流提取
istream& operator>>(istream& in, Date& d);
//流提取
istream& operator >> (istream& in, Date& d) {
	in >> d._year >> d._month >> d._day;
	return in;
}

源码

Date.h

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

class Date {
	//友元函数
	//友元函数可以访问私有成员
	friend ostream& operator<<(ostream& out, const Date& d);

	friend istream& operator>>(istream& in, Date& d);
public:
	Date(int year = 1990, int month = 1, int day = 1);
	//未加const前  Date* const this;
	//加上const后 const Date* const this;
	void print() const;
	Date(const Date&d);
	//默认是inline
	//用inline修饰的函数叫内联函数,可以提高编程效率
	int GetMonthDay(int year, int month) {
		//此数组需要频繁的调用,放入静态区
		//静态区的生命周期和程序的生命周期一样
		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;
		}
		else {
			return MonthDayArray[month];
		}
		
	}

	int GetYear() {
		return _year;
	}
	int GetMonth() {
		return _month;
	}
	int GetDay() {
		return _day;
	}

	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+(int day) const;
	//返回引用(Date&)直接操作原对象,无额外拷贝开销。
	Date& operator+=(int day);

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

	//d1++
	Date operator++(int);
	//++d2
	Date& operator++();

	int operator-(const Date& d);

	/*void operator<<(ostream& out);*/

	Date* operator&() {
		return this;
	}

	const Date* operator&() const {
		return this;
	}
//private:
private:
	int _year;
	int _month;
	int _day;
};

//流插入
ostream& operator<<(ostream& out, const Date& d);

//流提取
istream& operator>>(istream& in, Date& d);

Date.cpp

#include"Date.h"

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

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

Date::Date(const Date& d) {
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

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) {
			return _day < d._day;
		}
	}
	return false;
}

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

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

Date Date::operator+(int day) const {
	//日期加天数  原有的日期不变需要进行创建临时this
	//法一
	/*Date tmp = *this;
	tmp._day += day;

	while (tmp._day > GetMonthDay(tmp._year, tmp._month)) {
		tmp._day -= GetMonthDay(tmp._year, tmp._month);
		if (tmp._month > (tmp._month + 1) % 12) {
			tmp._year++;
		}
		tmp._month = (tmp._month + 1) % 12;
	}

	return tmp;*/

	//法二
	Date tmp = *this;
	//+=进行了赋值重载
	tmp += day;
	return tmp;
}

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

	while (_day > GetMonthDay(_year, _month)) {
		_day -= GetMonthDay(_year, _month);
		if (_month > (_month + 1)%12 ) {
			_year++;
		}
		_month = (_month + 1) % 12;
	}

	return *this; //返回当前对象的引用
}

Date Date::operator-(int day) const {
	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) {
			_month = 12;
			_year--;
		}
		_day += GetMonthDay(_year,_month);
	}
	return *this;
	
}

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

int Date:: operator-(const Date& d) {
	Date max = *this;
	Date min = d;
	int flag = 1;
	if (max < min) {
		swap(max, min);
		flag = -1;
	}
	int cnt = 0;
	while (max != min) {
		++min;
		cnt++;
	}
	return cnt * flag; 
}

//void Date::operator<<(ostream& out) {
//	//out就是cout
//	out << _year << "-" << _month << "-" << _day << endl;
//}
//d6 << cout;
//d6.operator<<(cout);

//流插入
ostream& operator<<(ostream& out, const Date& d) {
	//out就是cout
	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;
}

以上就是运算符重载的源码,只需要在main函数中进行相应的调用即可。
在这里插入图片描述
觉得我回答有用的话,记得点个关注哟!谢谢支持!


网站公告

今日签到

点亮在社区的每一天
去签到