[C++ Basics: 25]: [Important Template] C++ arithmetic (assignment) operator overloading and auto-increment and auto-decrement operator overloading [Take the Date date class as an example]

Series article description

This series of C++ related articles is only for the author’s study notes, and I will use my own understanding to record the study! The C++ learning series will be divided into three stages: basics, STL, and advanced data structures and algorithms . The relevant key contents are as follows:

  1. Basics : Classes and Objects (involving the three major features of C++, etc.);
  2. STL : Learn to use the STL related libraries provided by C++ ;
  3. High-order data structures and algorithms : Manually implement your own STL library and design and implement high-order data structures , such as B-tree, B+ tree, red-black tree, etc.

Study set:



Preface

  • The basic learning of classes has reached a certain stage, so the content that the author will share with you in the recent articles is: " 运算符重载小专题"! Currently updated: 关系运算符的重载(点击跳转), 输入输出运算符重载(点击跳转), solved the problem of comparison and input and output of custom types/objects!
  • In this article, the author will share with you 自定义类型 / 对象the calculation problem of ! That is: 自增自减运算符重载及算术运算符重载.

1. C++ arithmetic (assignment) operator overloading

1. Description

This article will +、-、+=、-=take as an example to design and implement arithmetic (assignment) operator overloading! [Note: In the previous description of operator overloading, it was mentioned that operator overloading cannot change its own meaning!


2. += / -= operator overloading [take the Date calendar class as an example]

符号含义

  • +=: Addition and assignment operator, assigns the result of adding the right operand to the left operand to the left operand!
  • -=: Subtraction AND assignment operator, assigns the result of subtracting the right operand from the left operand to the left operand

For our Date date class, the generally provided interfaces include: Calculate the date problem of adding or subtracting how many days after the current date!
At this time, calculation situations such as: 2023-6-16 += or + 15 days will appear! Obviously it is impossible to perform calculations using the original operators! (As shown below)

Insert image description here


2.1 Design ideas

Therefore, we need to overload our operators! 由于 + 或 - 可以基于 += 或 -= 来实现, so the author gives priority to implementing it += / -= 的重载!


Implement design ideas:

  1. 参数问题: Obviously you need to pass a number of days for recursive operation. The value does not need to be changed, so it can be modified with const.
  2. 日期迭代计算问题: Due to the date change involved, we 需要考虑的每个月的天数问题! And 可能出现闰年二月的情形!

2.2 Solution: Leap Year Problem (Introduction to Calculation Rules and Origin)

About: leap year problem!

  • 判断闰年的方式(1582年后的计算准则):该年可以被 400 整除 或 概念可以被 4 整除但不能被 100 整除,如:1900年不是闰年!

Regarding the origin of leap years: (The above calculation rules for leap years are those after 1582!)

  • The leap rules of the Gregorian calendar since 1582:
  • Ordinary leap year: If the Gregorian calendar year is a multiple of 4 and not a multiple of 100, it is a leap year (such as 2004, 2020, etc. are leap years).
  • Century leap year: The Gregorian calendar year is a hundred, and it must be a multiple of 400 to be a leap year (for example, 1900 is not a leap year, but 2000 is a leap year).
  • The convention before 1582: there is a leap year every four years; if A (positive number) in year A AD can be divided by 4, then it is a leap year; if B (positive number) in year B BC divides 4 and the remainder is 1, then it is a leap year. It's also a leap year.

Leap year judgment function implementation (as follows):

  • Parameters: year
  • Return value: yes/no
/* 闰年判断 */
bool IsLeapYear(int year) {
    
    
	return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

2.3 Days in the month issue

In order to facilitate calculation, the author designed the acquisition of the number of days in the month as a function!


Design ideas:

  • Parameters: year, month
  • Return value: int type (number of days)
  • Special processing: February is set to 28 days by default. If a leap year is encountered, the return value is +1;
  • 优化处理:由于获取月份天数可能使用频率较高,建议使用数组存储数据(设计如下:注意注释解释),并设定为静态数组!(避免每次调用函数新建数组的性能开销!)。

The code is implemented as follows:

/* 获取月份天数 */
int GetMonthDay(int year, int month) {
    
    
	/* 设置为静态数组提升效率 */
	/* 数组大小设置为 13 ,即为了直接使用 days[month] 访问到数据 */
	static int days[13] = {
    
     0,31,28,31,30,31,30,31,31,30,31,30,31 };
	
	if (month == 2 && IsLeapYear(year)) {
    
    
		return days[month] + 1;
	}
	return days[month];
}

2.4 Overloading design and implementation of += or -= operator

设计思路(注意点):


  1. The basic idea: always add/decrease the number of days to calculate the date. During the process, pay attention to judging the month change and year change!
  2. Parameters: Extrapolate the number of days passed.
  3. 返回值:日期的引用!
  4. 其他细节见注释!

+= 运算符重载(实现如下)

/* += 赋值运算符重载 */
Date& Date::operator += (const int day) {
    
    
	_day += day;									/* 直接递增天数 */
	while (_day > GetMonthDay(_year, _month)) {
    
    		/* 日期“合法性”判断 */
		/* 若:天数大于本月的固定天数,则 天数 - 本月天数,并将月份 + 1 */
		_day -= GetMonthDay(_year, _month);			/* 天数更跌 */
		_month += 1;								/* 月份更迭 */
		if (_month == 13) {
    
    							/* 年份更迭 */
			_month = 1;
			_year++;
		}
	}
	return *this;
}

-= 运算符重载(实现如下)

Date& Date::operator -= (const int day) {
    
    
	_day -= day;
	while (_day < 1) {
    
    								/* 判断天数合法性 */
		if (_month == 1) {
    
    							/* 特殊点:年份更迭 */
			_month = 13;							/* 注意此处:13,为的是后续统一的月份更迭计算 */
			_year--;
		}
		_day += GetMonthDay(_year, _month - 1);
		_month--;
	}
	return *this;
}

2.5 Test legend results

Insert image description here


3. + or - operator overloading

Combined with what was mentioned in the previous article to improve code reusability, you can directly use the existing += or -= to implement the key points of the + or - operator!

3.1 Overloading design, implementation and testing of + operator

+ 运算符重载(实现如下,注意注释提示)

  • 注意返回值:不是引用!
/* 
	在该函数中,不会去修改 Date 对象本身,
	而是返回一个新的对象,
	函数外部可以赋值给原对象或新对象!
*/
Date Date::operator+(const int day) const		
{
    
    
	// Date ret(*this);			/* 拷贝构造 */
	Date ret = *this;			
	ret += day;
	return ret;
}

Insert image description here


3.2 - Operator overloading design, implementation and testing

+ 运算符重载(实现如下,注意注释提示)

  • 注意返回值:不是引用!
/* 
	在该函数中,不会去修改 Date 对象本身,
	而是返回一个新的对象,
	函数外部可以赋值给原对象或新对象!
*/
Date Date::operator-(const int day) const		
{
    
    
	// Date ret(*this);			/* 拷贝构造 */
	Date ret = *this;			
	ret -= day;
	return ret;
}

Insert image description here


4. About *, /, *=, /= overload design and implementation

  • Regarding the design and implementation of overloading of *, /, *=, /=, according to the previous content, just follow the example!

2. C++ auto-increment and decrement operator overloading

1.Basic understanding

In C/C++, we can use ++ / --to perform increment and decrement operations on the data variables we define! These two operators can be described as a nightmare for newcomers to learn, especially in the final examination papers of college students, which have no practical significance in the evaluation of combinations of increment and decrement operators. [Basic usage is shown in the picture below!


In previous studies, you may have heard more or less: 前置自增自减 效率高于 后置自增自减. [Of course, there must be almost no difference under current compilers, and it has already been optimized]


It is known that 自增自减运算符分为:前置 和 后置, the main difference is:

  • Prepositioning means: giving priority to its own operation before participating in other operations;
  • The postposition is: first participate in other operations, and then perform its own operation!

Insert image description here


2. Implementation of overloading of auto-increment and auto-decrement operators

Front-end and rear-end ++ / --In actual use, we write the difference between front-end and rear-end, but what should we do when overloading?

  • 函数写法:使用函数重载!
  • 重载函数的区分方式: Use a parameter to distinguish ! 方案:前置使用无参形式,后置使用含参形式[ Note: After actual implementation, we do not need to display the parameter passed in the post-implementation process! The compiler will automatically identify the distinguishing parameters of the auto-increment and auto-decrement operator overloading]
  • 函数返回值:对象本身(引用返回)

The design code is as follows (note reuse of code):

2.1 Prefixed ++ or – operator overloading implementation

  • 前置 ++ ,即先 +1 再返回!
  • 前置 -- ,即先 -1 再返回!
/* 前置 ++ */
Date& Date::operator++()
{
    
    
	return *(this + 1);
}

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

2.2 Postfix ++ or – operator overloading implementation

  • 后置 ++ ,即先返回,再运算!(With the aid of: temporary objects)
  • 后置 -- ,即先返回,再运算!(With the aid of: temporary objects)
/* 后置 ++ */
Date& Date::operator++(int)
{
    
    
	Date ret(*this);
	*this += 1;
	return ret;
}

/* 后置 -- */
Date& Date::operator--(int)
{
    
    
	Date ret(*this);
	*this += 1;
	return ret;
}

2.3 Test result legend

Insert image description here


related articles

1. [C++ Basics Chapter: 21]: friend Friends asked four questions: What is a friend? Friend class? Friend function? When to use friends?
2. [C++ Basics: 22]: Const objects and const member functions/methods of classes and common problems involving const in classes!
3. [C++ Basics: 23]: [Important Template] Design and implementation of relational operator overloading: [ > , < , >= , <= , != , == ] overloading [taking the Date time class as an example]


Guess you like

Origin blog.csdn.net/weixin_53202576/article/details/131215397