重载运算符、日期类的实现(上课笔记)

运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号
函数原型:返回值类型 operator操作符(参数列表)

注意:
1、不能通过连接其他符号来创建新的操作符:比如operator@
2、重载操作符必须有一个类类型或者枚举类型的操作数
3、用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
4、作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
5、.* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
将‘重载“==”符号为成员函数///

class Date
{ 
public:
 Date(int year = 1900, int month = 1, int day = 1)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 
 // bool operator==(Date* this, const Date& d2)
 // 这里需要注意的是,左操作数是this指向的调用函数的对象
 bool operator==(const Date& d2)
 {
 return _year == d2._year;
 && _month == d2._month
 && _day == d2._day;
 }
 
private:
 int _year;
 int _month;
 int _day;
};
void Test ()
{
 Date d1(2018, 9, 26);
 Date d2(2018, 9, 27);
 cout<<(d1 == d2)<<endl;
}

当在我们尝试去重载operator<<,然后发现我们没办法将operator<<重载成成员函数。因为cout的输出流对象隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以我们要将operator<<重载成全局函数。但是这样的话,又会导致类外没办法访问成员,那么这里就需要友元来解决。

插入:友元函数
友元函数:打破了安全性封装性
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类内声明,声明时需要加friend关键字。
注意:
1、友元函数可访问类的私有和保护成员,但不是类的成员函数
2、友元函数不能用const修饰
3、友元函数可以在类定义的任何地方声明,不受类访问限定符限制
4、一个函数可以是多个类的友元函数
5、友元函数的调用与普通函数的调用和原理相同

class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
public:
 Date(int year, int month, int day)
 : _year(year)
 , _month(month)
 , _day(day)
 {}
 
private:
 int _year;
 int _month;
 int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
 _cout<<d._year<<"-"<<d._month<<"-"<<d._day;
 
 return _cout;
}

int main()
{
 Date d;
 cin>>d;
 cout<<d<<endl;
 return 0;
 }

实现日期类

日期类的成员数据

class Date{
private:
	int _year;
	int _month;
	int _day;
};

全缺省的构造函数

使用参数列表对成员数据初始化,提高效率

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

全缺省的构造函数

Date& Date::operator++(){
	_day++;
	int days = GetMonthDay(_year, _month);
	if (_day>days)
	{
		_day = 1;
		_month++;
		if (_month>12)
		{
			_month = 1;
			_year++;
		}
	}
	return *this;
}

拷贝构造函数

因为成员数据没有指针或者数组,所以用的是值拷贝(浅拷贝),否则必须为深拷贝。

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

赋值运算符重载

Date& Date::operator=(const Date& d){
	if (this!=&d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}

输出流<<重载

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

判断是否为闰年

bool Date::IsLeap(int year){
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

获取某年某月的天数

int Date::GetMonthDay(int year, int month)
{
	            //       1   2   3   4   5   6  7    8   9  10  11  12
	int arr[13] = { 29, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	if (month==2)
	{
		if (IsLeap(year))
		{
		  return arr[0];
		}	
	}
	return arr[month];
}

获取星期

设置:2022年12月1日:星期四,为标准

int Date::Getweek(int year,int month ,int day){
	//             0  1  2  3  4  5  6 
	char arr[7] = { 7, 1, 2, 3, 4, 5, 6 };

	//char  arr[8] = { "星期天","星期一","星期二" , "星期三", "星期四", "星期五", "星期六"};
	int week = 0;
	//2022年12月1日:星期四
	Date std(2022, 12, 1);
	Date d(year, month, day);
	int n = 0;
	if (std>d)
	{n = -(std - d);}
	else
	{n = std -d;}
	int m = 4 + n;
	if (m<0)
	{m = -m;}
	if (std>d)
	{
		if ((-n)<4)
		{
			week =4+n;
		}
		else{
			week = ((7 - (m % 7)) % 7);

		}
	}
	else
	{week = m % 7;}
	return arr[week];
}

重载日期+天数

Date Date::operator+(int n)
{
	int year = _year, month = _month, day = _day;
	int days = GetMonthDay(year, month);
	while ((day+n)>days)
	{
		month++;
		n -=days;
		if (month>12)
		{
			month = 1;
			year++;
		}
		days=GetMonthDay(year, month);
	}
	day+= n;
	return Date(year,month,day);
}

重载日期-天数

Date Date::operator-(int n){
	int year = _year, month = _month, day = _day,a_month=_month-1;
	int days;
	if (a_month==0)
	    days = GetMonthDay(year, 12);
	else
		days = GetMonthDay(year,a_month);
	while (n-day>0)
	{
		month--;
		a_month--;
		n -= days;
		if (month==0)
		{	
			year--;
			month = 12;
			a_month = month - 1;
		}	
		if (a_month==0)
	    	days = GetMonthDay(year, 12);
		else
			days = GetMonthDay(year,a_month);
	}
	day = day - n;
	return Date(year, month, day);
}

重载日期,前++、后++、+=

//前++
Date& Date::operator++(){
	_day++;
	int days = GetMonthDay(_year, _month);
	if (_day>days)
	{
		_day = 1;
		_month++;
		if (_month>12)
		{
			_month = 1;
			_year++;
		}
	}
	return *this;
}
//后++
Date Date::operator++(int){
	Date tmp = *this;
	*this += 1;
	return tmp;
}
//+=
Date& Date::operator+=(int day){
	Date t = *this + day;
	//Date t = *(this + day);
	*this = t;
	return *this;
}

重载日期,前–、后–、-=

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

>、<=运算符重载`

//>
bool Date::operator>(const Date& d){
	return(_year > d._year) ||
		  (_year == d._year&&_month > d._month) || 
		  (_year == d._year&&_month == d._month&&_day > d._day);
}
//<=
bool Date::operator<=(const Date& d) {
	return !(*this > d);
}

<、>=运算符重载

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

打印月历

void Date::printf_Month(int year, int month)
{
	int n = Date::Getweek(year,month,1);
	cout << "  星期天  " << "  星期一  " << "  星期二  " << "  星期三  " << "  星期四  " << "  星期五  " << "  星期六  " << endl;
	if (n==7)
	{
		for (int i = 1; i < GetMonthDay(year, month) + 1; i++)
		{
			cout << "     " << i << "     ";
			if ((i!=1)&&(Getweek(year, month,i) % 7==6))
			{
				cout << endl;
			}
		}
	}		
	else
	{
	 while (n)
		{
			cout << "           " ;
			n--;
		}
		n = Date::Getweek(year, month, 1);
		for (int i = 1; i <GetMonthDay(year, month) + 1; i++)
		{
			cout << "     " << i << "     ";
			if ((Getweek(year, month, i) % 7 )&& (Getweek(year, month, i) % 7 == 6))
			{
				cout << endl;
			}
		}
	}
	cout << endl;
}

日期-日期,返回天数

int Date::operator-(const Date& d){
	int n=0;
	int year = d._year, month = d._month, day = d._day;
	if (*this == d)       //判断是否为同一天
	{
		return 0;
	}
	if (*this>d)          //q-p,判断q、p的大小,给日期小的加天数,先使day相等、后month相等、最后year相等
	{
		if (_day > day)
		{
			n = _day - day;
			day = _day;
		}
		else
		{
			n = GetMonthDay(year,month) +_day - day;
			day = _day;
			month++;
			if (month == 13)
			{
				year++;
				month = 1;
			}
		}
		while (_month!=month)
		{
			n = n + GetMonthDay(year, month);
			month++;
			if (month==13)
			{
				year++;
				month = 1;
			}
		}
		while (_year!=year)
		{
			if (IsLeap(year))
			{
				n = n + 366;
			}
			else
			{
				n = n + 365;
			}
			year++;
		}
		return n;
	}
	else      //当q-p,p>q时
	{
		if (day > _day)
		{
			n = day - _day;
			_day = day;
		}
		else
		{
			n = GetMonthDay(_year, _month) + day - _day;
			_day = day;
			_month++;
			if (_month == 13)
			{
				_year++;
				_month = 1;
			}
		}
		while (month != _month)
		{
			n = n + GetMonthDay(_year, _month);
			_month++;
			if (_month == 13)
			{
				_year++;
				_month = 1;
			}
		}
		while (year !=_year)
		{
			if (IsLeap(_year))
			{
				n = n + 366;
			}
			else
			{
				n = n + 365;
			}
			_year++;
		}
		return n;
	}
}

总代码

#include<iostream>
using namespace std;

class Date
{
	friend ostream& operator<<(ostream &out, const Date& d);
public:
	// 获取某年某月的天数
	int GetMonthDay(int year, int month);
	//获取星期
	int Getweek(int year,int month,int day);
	//打印月历
	void printf_Month(int year, int month);
	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1) :_year(year), _month(month), _day(day)
	{}
	// 拷贝构造函数
	// d2(d1)
	Date(const Date& d);

	// 赋值运算符重载
	// d2 = d3 -> d2.operator=(&d2, d3)
	Date& operator=(const Date& d);

	// 析构函数
	~Date()
	{}
public:
	// 日期+=天数
	Date& operator+=(int day);
	// 日期+天数
	Date operator+(int day);
	// 日期-天数
	Date operator-(int day);
	// 日期-=天数
	Date& operator-=(int day);
public:
	// 前置++
	Date& operator++();
	// 后置++
	Date operator++(int);
	// 后置--
	Date operator--(int);
	// 前置--
	Date& operator--();
public:
	// >运算符重载
	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);
public:
	// 日期-日期 返回天数
	int operator-(const Date& d);
protected:
	bool IsLeap(int year);
private:
	int _year;
	int _month;
	int _day;
};

bool Date::IsLeap(int year){
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

int Date::GetMonthDay(int year, int month)
{
	            //       1   2   3   4   5   6  7    8   9  10  11  12
	int arr[13] = { 29, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	if (month==2)
	{
		if (IsLeap(year))
		{
		  return arr[0];
		}	
	}
	return arr[month];
}

//输出流重载
ostream& operator<<(ostream &out ,const Date& d){
	out <<d._year<<"年"<<d._month<<"月"<<d._day<<"日";
	return out;
}

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

Date& Date::operator=(const Date& d){
	if (this!=&d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}
bool Date::operator==(const Date& d){
	return (_year == d._year) && (_month == d._month) && (_day == d._day);
}

// 日期+天数
Date Date::operator+(int n)
{
	int year = _year, month = _month, day = _day;
	int days = GetMonthDay(year, month);
	while ((day+n)>days)
	{
		month++;
		n -=days;
		if (month>12)
		{
			month = 1;
			year++;
		}
		days=GetMonthDay(year, month);
	}
	day+= n;
	return Date(year,month,day);
}

Date Date::operator-(int n){
	int year = _year, month = _month, day = _day,a_month=_month-1;
	int days;
	if (a_month==0)
	    days = GetMonthDay(year, 12);
	else
		days = GetMonthDay(year,a_month);
	while (n-day>0)
	{
		month--;
		a_month--;
		n -= days;
		if (month==0)
		{	
			year--;
			month = 12;
			a_month = month - 1;
		}	
		if (a_month==0)
	    	days = GetMonthDay(year, 12);
		else
			days = GetMonthDay(year,a_month);
	}
	day = day - n;
	return Date(year, month, day);
}

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

Date& Date::operator+=(int day){
	Date t = *this + day;
	//Date t = *(this + day);
	*this = t;
	return *this;
}

Date& Date::operator++(){
	_day++;
	int days = GetMonthDay(_year, _month);
	if (_day>days)
	{
		_day = 1;
		_month++;
		if (_month>12)
		{
			_month = 1;
			_year++;
		}
	}
	return *this;
}

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

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

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

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

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

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

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

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

int Date::operator-(const Date& d){
	int n=0;
	int year = d._year, month = d._month, day = d._day;
	if (*this == d)
	{
		return 0;
	}
	if (*this>d)
	{
		if (_day > day)
		{
			n = _day - day;
			day = _day;
		}
		else
		{
			n = GetMonthDay(year,month) +_day - day;
			day = _day;
			month++;
			if (month == 13)
			{
				year++;
				month = 1;
			}
		}
		while (_month!=month)
		{
			n = n + GetMonthDay(year, month);
			month++;
			if (month==13)
			{
				year++;
				month = 1;
			}
		}
		while (_year!=year)
		{
			if (IsLeap(year))
			{
				n = n + 366;
			}
			else
			{
				n = n + 365;
			}
			year++;
		}
		return n;
	}
	else
	{
		if (day > _day)
		{
			n = day - _day;
			_day = day;
		}
		else
		{
			n = GetMonthDay(_year, _month) + day - _day;
			_day = day;
			_month++;
			if (_month == 13)
			{
				_year++;
				_month = 1;
			}
		}
		while (month != _month)
		{
			n = n + GetMonthDay(_year, _month);
			_month++;
			if (_month == 13)
			{
				_year++;
				_month = 1;
			}
		}
		while (year !=_year)
		{
			if (IsLeap(_year))
			{
				n = n + 366;
			}
			else
			{
				n = n + 365;
			}
			_year++;
		}
		return n;
	}
}
int Date::Getweek(int year,int month ,int day){
	//             0  1  2  3  4  5  6 
	char arr[7] = { 7, 1, 2, 3, 4, 5, 6 };
	int week = 0;
	//2022年12月1日:星期四
	Date std(2022, 12, 1);
	Date d(year, month, day);
	int n = 0;
	if (std>d)
	{n = -(std - d);}
	else
	{n = std -d;}
	int m = 4 + n;
	if (m<0)
	{m = -m;}
	if (std>d)
	{
		if ((-n)<4)
		{
			week =4+n;
		}
		else{
			week = ((7 - (m % 7)) % 7);

		}
	}
	else
	{week = m % 7;}
	return arr[week];
}
void Date::printf_Month(int year, int month)
{
	int n = Date::Getweek(year,month,1);
	cout << "  星期天  " << "  星期一  " << "  星期二  " << "  星期三  " << "  星期四  " << "  星期五  " << "  星期六  " << endl;
	if (n==7)
	{
		for (int i = 1; i < GetMonthDay(year, month) + 1; i++)
		{
			cout << "     " << i << "     ";
			if ((i!=1)&&(Getweek(year, month,i) % 7==6))
			{
				cout << endl;
			}
		}
	}		
	else
	{
	 while (n)
		{
			cout << "           " ;
			n--;
		}
		n = Date::Getweek(year, month, 1);
		for (int i = 1; i <GetMonthDay(year, month) + 1; i++)
		{
			cout << "     " << i << "     ";
			if ((Getweek(year, month, i) % 7 )&& (Getweek(year, month, i) % 7 == 6))
			{
				cout << endl;
			}
		}
	}
	cout << endl;
}


void main(){
	Date a(2024, 2, 20);
	cout << "a : " << a << endl;
	int days = a.GetMonthDay(2023, 2);
	cout << "days = " << days << endl;

	//拷贝构造
	Date b = a;
	cout << "b : " << b << endl;

	//赋值语句
	Date c;
	c = a;
	cout << "c : " << c << endl;

	Date d(2022, 7, 12);
	if (d > c)
	{
		cout << "d >c " << endl;
	}
	else
	{
		cout << " d<=c " << endl;
	}
	cout << "d : " << d << endl;

	//Date e=d +30;
	//cout <<"d : (+30)"<< d;   
	//cout <<"e : "<<e;
	d += 1765;
	cout << "d : (+=1765) " << d << endl;
	Date f = d - 1765;
	cout << "f : (d-1765)" << f << endl;

	//前++
	Date g(2000, 2, 28);
    cout << "g = " << g<<endl;
	++g;
	cout << "++g= " << g<<endl;

	//测试日期减日期
	int n = d - f;
	cout << "n = " << n << endl;
	int n1 = f - d;
	cout << "n1 = " << n1 << endl;
	
	//测试给一个日期,得到星期
	Date h(2022, 11, 12);
	int week = h.Getweek(2022, 11, 12);
	cout << h << "是星期" << week << endl;
	
	//测试月历,以2022年为例
	cout << "                 2022年1月                 " << endl << endl << endl;
	h.printf_Month(2022, 1);
	cout << endl << endl << endl << endl;

	cout << "                 2022年2月                 " << endl << endl << endl;
	h.printf_Month(2022, 2);
	cout << endl << endl << endl << endl;

	cout << "                 2022年3月                 " << endl << endl << endl;
	h.printf_Month(2022, 3);
	cout << endl << endl << endl << endl;

	cout << "                 2022年4月                 " << endl << endl << endl;
	h.printf_Month(2022, 4);
	cout << endl << endl << endl << endl;

	cout << "                 2022年5月                 " << endl << endl << endl;
	h.printf_Month(2022, 5);
	cout << endl << endl << endl << endl;

	cout << "                 2022年6月                 " << endl << endl << endl;
	h.printf_Month(2022, 6);
	cout << endl << endl << endl << endl;

	cout << "                 2022年7月                 " << endl << endl << endl;
	h.printf_Month(2022, 7);
	cout << endl << endl << endl << endl;

	cout << "                 2022年8月                 " << endl << endl << endl;
	h.printf_Month(2022, 8);
	cout << endl << endl << endl << endl;

	cout << "                 2022年9月                 " << endl << endl << endl;
	h.printf_Month(2022, 9);
	cout << endl << endl << endl << endl;

	cout << "                 2022年10月                 " << endl << endl << endl;
	h.printf_Month(2022, 10);
	cout << endl << endl << endl << endl;

	cout << "                 2022年11月                 " << endl << endl << endl;
	h.printf_Month(2022, 11);
	cout << endl << endl << endl << endl;

	cout << "                 2022年12月                 " << endl << endl << endl;
	h.printf_Month(2022, 12);
	cout << endl << endl << endl << endl;

}

运行结果:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值