[take you through C + +] operator overloading (assignment operator overloading) turns out to be such a thing

Posted by Jeyush on Sat, 08 Jan 2022 12:02:09 +0100

Operator overloading

In order to enhance the readability of the code, C + + introduces operator overloading. Operator overloading is a function with a special function name. Its purpose is to make user-defined types operate directly with operators like built-in types. Operator overloading is to give multiple meanings to existing operators, so that the same operator can produce different behaviors when used for different types of data. The purpose of operator overloading is to enable operators in C + + to operate on objects.

The operator overloaded function name is: the keyword operator is followed by the operator symbol that needs to be overloaded.

Function prototype: return value operator operator (parameter list)
The format is as follows:

<Return type specifier> operator <Operator symbol>(<Parameter table>)
{
 
     <Function body>
 
}

Operator overloaded functions also have their own return value types, function names, and parameter lists. Its return value type and parameter list are similar to ordinary functions.

Let's write a simple example

#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
public://Originally, it should be private, but this operator overload will not be accessible
//private:
	int _year;
	int _month;
	int _day;
};
//1, The parameter type is set to reference and decorated with const
 //Since it is a user-defined type parameter passing, if we use value passing parameter passing, we will call the copy constructor additionally, so it is best to use reference parameters for function parameters
 //Secondly, for parameters, we will not modify them in the function body, so we'd better add const to modify them.
bool operator==(const Date& x1,const Date& x2)
	{
		return x1._year == x2._year
			&& x1._month == x2._month
			&& x1._day == x2._day;
	}
int mian()
{
	Date d1(2020, 10, 22);
	Date d2(2021, 5, 22);
	Date d3(2023, 3, 22);

	//Operators are used for built-in type variables by default
	//If you want to use these operators for variables of custom types, you have to overload the operators yourself
	//Operator overloading means that we write a function definition to implement the behavior of the operator here
	d1 == d2;
	return 0;

}

At this time, operator overloading can judge the equivalence of date classes, but it changes the private in the original class to public. If the access qualifier is not changed, you will face the problem of accessing private member variables - > how to solve it?

We can put the operator overload as a member function in the date class, so there is no access restriction

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

bool operator==(const Date& x1,const Date& x2)
	{
		return x1._year == x2._year
			&& x1._month == x2._month
			&& x1._day == x2._day;
	}
public://Originally, it should be private, but this operator overload will not be accessible
//private:
	int _year;
	int _month;
	int _day;
};

However, we will see an error report:

This is because:

When the operator overload is a global function, the number of parameters is equal to the number of operators (i.e. the number of operands); When the operator is overloaded as a member function, the number of parameters is equal to the number of operators minus one.

Let's explain:
The parameter requirement of operator overloading is that the number of parameters is equal to the number of operators (i.e. the number of operands). When the operator overloading is a member function, in addition to the two parameters we see, there is an implicit this pointer, which leads to the error.

Therefore, we make the following modifications to the function overload:

bool operator==(const Date& x)//bool operator==(Date* this,const Date&x)
	{
		return _year == x_year
			&& _month == x_month
			&& _day == x_day;
//In fact:
//	    return this->_year == x._year
//			&& this->_month == x._month
//			&& this->_day == x._day;*/
	}

Call again:

 d1==d2;
//Or D1 operator==(d2);

The above two calling methods are actually the same. Let's look at them from the perspective of assembly:

After understanding the principle, let's do another one:

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

Assignment operator overload

According to the operator overloading rules, we will overload the assignment (=) operator.

class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
//Assignment operator overload
	void operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()//output
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

	private:
	//public:
	int _year;
	int _month;
	int _day;	
};
int main()
{
	Date d1(2021, 10, 11);
	Date d2(2020, 11, 11);
	Date d3(2021, 11, 11);
	d1 = d3;
	d1.Print();
	d3.Print();
	//Overload of assignment operator: used for copying between two and that defined object
	//Copy construction: use an existing object to construct and initialize another object to be created
	//Copy structure: d3=d5;
	return 0;

}

Operation results:

We can see that d3 is assigned to d1
However, this is not enough. We know that the characteristic of assignment can be continuous assignment, such as:

d1=d2=d3;
//Assign d3 to d2, and then assign d2 as the return value to d1

Let's see if we can:

Obviously not, because the assignment overload does not set the return value to d1=d2=d3; For example, d2 cannot be assigned to d1 as the return value, so we make the following modifications:

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

Summary of details:

1, The parameter type is set to reference and decorated with const

The first parameter of the overloaded function of the assignment operator is the this pointer by default, and the second parameter is the right operand of our assignment operator.

Since it is a user-defined type parameter passing, if we use value passing parameter passing, we will call the copy constructor again. Therefore, it is best to use reference passing parameter for the second parameter of the function (the first parameter is the default this pointer). Secondly, the second parameter, that is, the right operand of the assignment operator, will not be modified in the function body, so we'd better add const to modify it.

2, The return value of the function is returned by reference
  if we only use the assignment operator in the way of d2 = d1, there is no need for the return value of the overloaded function of the assignment operator, because d2 has been modified through the this pointer in the function body. However, in order to support continuous assignment, that is, d3 = d2 = d1, we need to set a return value for the function, and obviously, the return value should be the left operand of the assignment operator, that is, the object pointed to by this pointer.
  the same as using reference to pass parameters, in order to avoid unnecessary copying, we'd better use reference return, because the object pointed to by this pointer in the function scope has not been destroyed, so reference return can be used.

3, The reference returns * this
  when the assignment operation is completed, we should return the left operand of the assignment operator. In the function body, we can only access the left operand through the this pointer, so to return the left operand, we can only return * this.
4, Check whether you are assigning a value to yourself before assigning a value
  if d1 = d1, we don't have to assign, because it's not necessary to assign to ourselves. Therefore, before the assignment operation, you can first judge whether you are assigning a value to yourself to avoid unnecessary assignment operation.

– the End –

The above is the related content of [operator overloading (assignment operator overloading) turned out to be such a thing] I shared. Thank you for reading!

Pay attention to the author, keep reading the author's articles and learn more!
https://blog.csdn.net/weixin_53306029?spm=1001.2014.3001.5343

2022.1.8
--------

Topics: C++ Back-end