当前位置: 首页 > article >正文

C++类和对象(5)——运算符重载(以日期类为例)

运算符重载的作用

假设我们此时实现了日期类的运算符重载,我们就可以

实现如图的很多功能,完成日期计算器的底层代码。

运算符重载关键字

运算符重载的关键字是operator。

比如你想重载‘+’运算符,那么语法格式就是

返回类型 + operator + ‘+’ +(形参),

以日期类为例,

Date operator+(int day)const;

有const关键字是因为这个重载不修改对象本身(*this)的值,如下图的d1不被改变。

Date d3 = d1 + 100;

以下运算符不能重载:

1.     ?:

2.     sizeof

3.     

4.      :: 

5.      .*

日期类的运算符重载

以下是日期类的声明,待会逐一实现运算符重载。

#pragma once
#include<iostream>
using namespace std;
class Date
{
	friend ostream& operator<<(ostream& out, const Date& d);

	friend istream& operator>>(istream& out, Date& d);

public:

	Date(int year = 1990, int month = 1, int day = 1);

	~Date();

	int GetMonthDay(int year, int month)
	{
		static int a[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };
		if ((month == 2) && ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)))
		{
			return 29;
		}
		return a[month];
	}

	Date(const Date& d);

	void print()const;

	Date& operator=(const Date& d);

	Date& operator+=(int day);

	Date operator+(int day)const;

	Date& operator-=(int day);

	Date operator-(int day)const;

	Date& operator++();

	Date operator++(int);

	Date& operator--();

	Date operator--(int);

	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;

	int operator-(const Date& d)const;

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

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

istream& operator>>(istream& out, Date& d);

构造、拷贝构造、析构函数的实现(非重载内容可跳过)

我以前写过两篇博客介绍构造、拷贝构造、析构函数,感兴趣的朋友可以看看。

http://t.csdnimg.cn/DedK1

http://t.csdnimg.cn/LWuj2

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

Date::~Date() {}

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

重载 =

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

我们运用的场景如下:

Date d1(2000, 1, 1);
Date d2(2001, 2, 2);
d1 = d2;

当我们重载=时,将d2赋值给d1,改变了d1的值,所以重载=的返回类型为 Date& ,返回*this

重载+=

要实现日期+天数的功能,我们要先编写一个函数GetMonthDay,这个函数可以直接写在类的声明里。

int GetMonthDay(int year, int month)
{
	static int a[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };
	if ((month == 2) && ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)))
	{
		return 29;
	}
	return a[month];
}

接着实现+=的重载

Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		++_month;
		if (_month == 13)
		{
			_month = 1;
			++_year;
		}
	}
	return *this;
}

通过while循环实现天数的正确叠加、月份和年份的增加。

注意返回类型是Date&,因为

Date d1(2000, 1, 1);
d1 += d1 + 100;

d1重载+=时,d1的值会被改变 !

重载+

这一步我们可以通过写过的的+=重载偷懒😎

Date Date::operator+(int day)const
{
	Date temp = *this;
//+=已经重载过了,可以直接用
	temp += day;
	return temp;
}

注意返回类型是Date,因为

Date d3 = d1 + 100;

调用的时候是d1重载+,d1的值没有被改变。

重载-=(计算这个日期前x天是几号)

Date& Date::operator-=(int day)
{
	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			_month = 12;
			--_year;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

重载-

Date Date::operator-(int day)const
{
	Date temp = *this;
	temp -= day;
	return temp;
}

重载前置++

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

这里也用+=重载偷懒了😉

重载后置++

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

注意,为了区分后置++与前置++,后置++的传参有一个int形参!

并且,后置++的返回值为Date, 前置++的返回值为Date&;

因为:

如上图所示,

d2的值与d1的原始值相等 ,

当d1++用过一次之后,d1的值才会+1.

这也就解释了为什么后置++的返回值为Date, 前置++的返回值为Date&;

后置++需要temp变量存放*this的值。

重载前置--

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

用-=偷懒。。

重载后置--

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

重载>

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

重载==

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) || (*this == d);
}

重载<

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

重载<=

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

重载!=

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

重载<<

ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << '-' << d._month << '-' << d._day << endl;
	return out;
}

这不是Date类的成员函数,而是全局函数。

为了能访问私有成员_year,_month,_day,

我们要把这个函数变成友元函数,如下:

重载>>

//这里的形参Date& d的前面不能添加const关键字,因为d的值待会要改变
istream& operator>>(istream& in, Date& d)
{
	cout << "" << endl;
	in >> d._year >> d._month >> d._day;
	return in;
}

重载-(计算两个时间之间差几天)

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

我的另一篇博客讲了详细的实现思路http://t.csdnimg.cn/gk7cK


http://www.kler.cn/a/283613.html

相关文章:

  • 前端请求后端php接口跨域 cors问题
  • 【最新版】Stable Diffusion4.9(AI绘画)下载及安装教程(附软件安装包)!
  • 【练习案例】30个 CSS Javascript 加载器动画效果
  • ArkTs简单入门案例:简单的图片切换应用界面
  • 界面控件Kendo UI for Angular中文教程:如何构建带图表的仪表板?(一)
  • 微服务day07
  • 数据库,SQL和 MySql的三者关系
  • 智能听诊器:开启宠物健康管理新维度
  • 【网络安全】打开这份“开学礼” 谨防骗子“冲业绩”
  • 【Spring Boot 3】【Web】同时启用 HTTP 和 HTTPS
  • vue3+ts+vite项目代码检查报错(vue-tsc)
  • 解决Nginx负载均衡中的慢启动问题:策略与实践
  • k8s-pod 实战八 (gRPC 探测详细分析)
  • Cpp学习手册-基础学习
  • Python 处理 PDF 文件(PyPDF2, ReportLab)
  • 云轴科技ZStack与鼎甲科技共创数据保护新篇章
  • 显示中文字体问题解决:ImportError: The _imagingft C module is not installed
  • 最简洁!四步完成C#——opencv环境配置
  • 大模型企业应用落地系列八》基于大模型的对话式推荐系统》用户交互层
  • Python编码系列—Python CI/CD 实战:构建高效的自动化流程
  • MySQL集群基本概率
  • MySQL 延迟从库介绍
  • 基于OpenCV+MFC的KCF测速软件
  • Java面试题--1基础篇-01 __八股文 备战春招,秋招
  • 餐饮_零售_麻辣烫_水果店_零食店_生鲜店等收银系统
  • 代码随想录算法训练营day55:图论05:并查集