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

CD20.【C++ Dev】类和对象(11) 日期类对象的成员函数(++、--、日期-日期)

目录

1.operator++重载

1.知识回顾

2.++运算符重载的实现

前置++

格式

operator++()

后置++

格式

其他说明:operator++(int)参数的值

operator++(int)

测试代码

2.operator--重载

3.operator-=重载

测试代码

提问

修复

4.operator-实现日期-天数

5.operator-实现日期-日期

方法1

方法2

代码

测试代码

6.LeetCode练习

代码

提交结果


1.operator++重载

1.知识回顾

前置++和后置++的区别:

参见15.【C语言】初识操作符 下文章

2.++运算符重载的实现

要考虑前置和后置,不能简单实现为d+=1,且前置++和后置++有规定的格式

前置++

格式
引用返回 operator++()//隐含第一个参数*this
{
    //do_something
}
operator++()

对于CD19.【C++ Dev】类和对象(10) 日期类对象的成员函数(日期+天数)文章提到的日期类而言,前置++可复用operator+=,可以这样写:先++,后使用,返回加过的*this

Date& Date::operator++()//隐含第一个参数*this
{
	*this += 1;
	return *this;
}

后置++

格式

两个重载的运算符可以实现,且只能使用函数重载,为了与前置++做区分,后置++的参数表要与前置++区分,

C++标准规定:增加一个int参数(只能用int,不能使用其他类型,否则报错),没有实际的意义,仅用于占位构成重载,operator++内部不使用这个参数

 (来自Microsoft Learn Increment and Decrement Operator Overloading (C++))

拷贝返回 operator++(int)//隐含第一个参数*this
{
    //do_something
}
其他说明:operator++(int)参数的值

测试以下代码:

#include "Date.h"
int main()
{
    Date d1(2025, 3, 27);
    Date d3 = d1++;
    Date d4 = d3++;
    return 0;
}

下断点到Date d3 = d1++一般而言,参数要压栈,可转到反汇编查看push的参数

可以看到是传0的,这个是C++标准规定的

operator++(int)

先使用,后++,返回加之前的*this

需要使用临时对象,由于operator++返回时,临时对象会销毁,因此需要拷贝返回(Date)

Date Date::operator++(int)//隐含第一个参数*this
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

测试代码

#include "Date.h"
int main()
{
    Date d1(2025, 3, 27);
    Date d2 = ++d1;//operator++完整的实参表(&d1)
    Date d3 = d1++;//operator++完整的实参表(&d1,0)
    d2.Print();
    d3.Print();
    return 0;
}

运行结果:两次打印的日期是一样的

 

2.operator--重载

原理和++一样,复用operator-=即可,这里只展示代码

//前置--
Date& Date::operator--()//隐含第一个参数*this
{
	*this -= 1;
	return *this;
}

//后置--
Date Date::operator--(int)//隐含第一个参数*this
{
	Date tmp(*this);
	*this -= 1;
	return tmp;
}

下面将实现operator-=

3.operator-=重载

和CD19.【C++ Dev】类和对象(10) 日期类对象的成员函数(日期+天数)文章的operator+=思想类似,先与日做减法(可能会出现负数,之后处理),如果不够减向月借位,月不够向年借位,最终保证日大于0即可

Date& Date::operator-=(int day)
{
	_day -= day;
	while (_day <= 0)
	{
		_month--;
		//if判断必须放在前面,为了应对_month从1减完变成0
		if (_month <= 0)//也可以写成if (_month == 0)
		{
			_year--;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);

	}
	return *this;
}

测试代码

#include "Date.h"
int main()
{
    Date d1(2025, 3, 27);
    d1 -= 100;
    d1.Print();
    return 0;
}

运行结果

提问

上方代码的operator-=真的没有问题吗?

如果使用此测试代码:

#include "Date.h"
int main()
{
    Date d1(2025, 3, 27);
    d1 -= -100;
    d1.Print();
    return 0;
}

运行结果:日超出范围

 

修复

需要添加判断:减一个负数等于加上这个数的相反数

Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		*this += -day;
		return *this;
	}
	_day -= day;
	while (_day <= 0)
	{
		_month--;
		//if判断必须放在前面,为了应对_month从1减完变成0
		if (_month <= 0)
		{
			_year--;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);

	}
	return *this;
}

 d1 -= -100的运行结果:

4.operator-实现日期-天数

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

5.operator-实现日期-日期

方法1

先让日和月相等,之后算多少年,例如2025/3/27和2024/8/8-->先计算2025/3/27和2024/3/27之间的天数,再算2024/3/2和2024/8/8之间的天数,但这样算比较麻烦,不推荐

方法2

反复调用operator--,让大日期--,直到等于小日期或者反复调用operator++,让小日期++,直到等于大日期,下面代码使用operator--

先找出谁是大日期,谁是小日期,再--

代码

int Date::operator-(const Date& d2)
{
	Date bigdate;
	Date smalldate;
	int ret = 0;
	if (*this < d2)
	{
		bigdate = d2;
		smalldate = *this;
	}
	else
	{
		bigdate = *this;
		smalldate = d2;
	}
	while (bigdate != smalldate)//!=比用>快!
	{
		bigdate--;
		ret++;
	}
	return ret;
}

测试代码

#include "Date.h"
int main()
{
	Date d1(2025, 3, 27);
	Date d2(2024, 8, 8);
	cout << (d1 - d2) << endl;
	return 0;
}

运行结果

6.LeetCode练习

日期-日期问题:

1360. 日期之间隔几天 - 力扣(LeetCode)

代码

套用本篇文章和CD19.【C++ Dev】类和对象(10) 日期类对象的成员函数(日期+天数)文章的代码

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

    Date(const Date& x)
    {   
	    _year = x._year;
	    _month = x._month;
	    _day = x._day;
    }
	int GetMonthDay(int year,int month)
    {
	    static int day[] = { 0,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 day[month];
    }
    bool operator== (const Date& d2)
    {
	    return ((_year == d2._year) && (_month == d2._month) && (_day == d2._day));
    }

    bool operator!=(const Date& d2)
    {
	    return !(*this == d2);
    
    }
    Date& operator-=(int day)
    {
        _day -= day;
        while (_day <= 0)
        {
            _month--;
            //if判断必须放在前面,为了应对_month从1减完变成0
            if (_month <= 0)
            {
                _year--;
                _month = 12;
            }
            _day += GetMonthDay(_year, _month);

        }
        return *this;
    }

	Date operator--(int)//后置--
    {
    	Date tmp(*this);
    	*this -= 1;
    	return tmp;
    
    }
    bool operator< (const Date& d2)
    {
        if (_year < d2._year)
            return true;
        else if (_year == d2._year && _month < d2._month)
            return true;
        else if (_year == d2._year && _month == d2._month && _day < d2._day)
            return true;
        return false;
    }
	int operator-(const Date& d2)
    {
        Date bigdate;
        Date smalldate;
        int ret = 0;
        if (*this < d2)
        {
            bigdate = d2;
            smalldate = *this;  
        }
        else
        {
            bigdate = *this;
            smalldate = d2;
        }
        while (bigdate != smalldate)
        {
            bigdate--;
            ret++;
        }
        return ret;
    }

	int _year;
	int _month;
	int _day;
};

class Solution {
public:
    int daysBetweenDates(string date1, string date2) 
    {
        int date1_year=stoi(date1.substr(0,4));
        int date1_month=stoi(date1.substr(5,2));
        int date1_day=stoi(date1.substr(8,2));
        int date2_year=stoi(date2.substr(0,4));
        int date2_month=stoi(date2.substr(5,2));
        int date2_day=stoi(date2.substr(8,2));
        Date d1(date1_year,date1_month,date1_day);
        Date d2(date2_year,date2_month,date2_day);
        return d1-d2;
    }
};

提交结果

相关文章:

  • C++:allocator类(动态数组续)
  • Playwright设置base_url的三种方式
  • BUUCTF-web刷题篇(3)
  • PHP如何搭建设置代理http并加密使用?
  • PPT——组合SCI论文图片
  • 深入解析:MySQL 中 NULL 值是否占用 1 bit 存储空间?
  • “三小时搞定AI工具开发“:基于MCP的Node.js极简实践
  • Optional的stream方法,flatMap, filter应用
  • Imgui处理glfw的鼠标键盘的方法
  • stable diffusion webui 更改为python3.11版本运行Windows11
  • 【C++】右值引用与完美转发
  • 软件工程面试题(十)
  • 妙用《甄嬛传》中的选妃来记忆概率论中的乘法公式
  • 交换技术综合实验
  • 第四章.4.3.1ESP32传感器数据采集与滤波处理实战教程
  • 从0开始——在PlatformIO下开展STM32单片机的HAL库函数编程指南
  • ​​​​​​​​​​​​​​Spring Boot数据库连接池
  • Vue学习笔记集--computed
  • 蓝桥杯-特殊的多边形(dfs/前缀和)
  • 指针和引用
  • 莫名的硝烟|“我们最好记住1931年9月18日这个日子”
  • 三大猪企一季度同比均实现扭亏为盈,营收同比均实现增长
  • 锦江酒店:第一季度营业收入约29.42亿元,境内酒店出租率同比增长
  • 新开发银行如何开启第二个“金色十年”?
  • 匈牙利国会通过退出国际刑事法院的决定
  • 跟着京剧电影游运河,京杭大运河沿线六城举行京剧电影展映