[C++ Learning] Classes and Objects | Operator Overloading | Assignment Operator Overloading

 Written in front:

In the previous article, we learned about copy construction and explored the use of operator overloading.

If you are interested, you can check it out: http://t.csdn.cn/dkD1g

Today we continue to learn about classes and objects.

Table of contents

 Written in front:

1. Operator overloading

2. Assignment operator overloading

Write at the end:


1. Operator overloading

Take a look at this code:

#include <iostream>
using namespace std;

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

	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

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

int main()
{
	Date d1(2023, 1, 1);
	Date d2(2023, 2, 2);
	cout << (d1 < d2) << endl;

	return 0;
}

If we want to compare the size of this date class,

We can write a special size comparison function to complete it,

But after learning operator overloading, we can directly use operator overloading to complete the comparison,

However, if the operator overloading is placed outside the class, then we must put the member variables of the class in public,

This destroys the encapsulation of the class, so what if we put this function directly into the class?

Look at the code:

#include <iostream>
using namespace std;

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

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

	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2023, 1, 1);
	Date d2(2023, 2, 2);
	cout << (d1 < d2) << endl;

	return 0;
}

The compiler throws an error:

Says this operator function has too many arguments,

why is that? 

Because the member functions in the class have a hidden this pointer,

So we leave one parameter for comparison, and the other parameter is the this pointer,

Look at the code:

#include <iostream>
using namespace std;

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

	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 false;
	}

	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2023, 1, 1);
	Date d2(2023, 2, 2);
	
	cout << (d1 < d2) << endl;
	cout << d1.operator<(d2) << endl;

	return 0;
}

In fact, the expression d1 < d2 is essentially a function call,

That is, d1.operator<(d2) .

pay attention:

Operator overloading can only overload operators that exist in C++, not self-created;

An overloaded operator must have a class type parameter;

Operators for built-in types, whose meaning cannot be changed;

When overloaded as a class type, the formal parameter seems to be one less than the operand, but in fact the first parameter is the hidden this pointer;

Notice!  .* :: sizeof ?: .   ) These 5 operators cannot be overloaded! ! !

2. Assignment operator overloading

Take a look at this code:

#include <iostream>
using namespace std;

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

	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2023, 1, 1);
	Date d2;

	//如果我们使用一个对象赋值一个对象,就会调用赋值运算符重载
	d1 = d2;

	return 0;
}

At this time, you need to use assignment operator overloading.

However, it should be noted here that copy construction is different from assignment operator overloading.

Copy construction is to use an existing object to initialize another object,

Whereas assignment operator overloading is a copy copy between two already existing objects.

So how to achieve it?

Look at the code:

#include <iostream>
using namespace std;

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

	void operator=(const Date& x) {
		_year = x._year;
		_month = x._month;
		_day = x._day;
	}

	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2023, 1, 1);
	Date d2;

	//如果我们使用一个对象赋值一个对象,就会调用赋值运算符重载
	d1 = d2;

	return 0;
}

Is this really all right?

There is no error when running the compiler, it seems to be successful, but,

If you create three objects, you find:

He cannot support continuous assignment,

The operation: d1 = d2 = d3 is not supported,

To make it support continuous assignment, we need to add a return value to this assignment operator overload function:

Look at the code:

#include <iostream>
using namespace std;

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

	// d1 = d2
	Date& operator=(const Date& x) {
		_year = x._year;
		_month = x._month;
		_day = x._day;
		return *this;
	}

	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2023, 1, 1);
	Date d2;

	//如果我们使用一个对象赋值一个对象,就会调用赋值运算符重载
	d1 = d2;

	return 0;
}

In this way, we can return the value of the successfully assigned d1,

And, is our d1 object still there after it goes out of the scope of the function, still there,

So we use reference return to improve efficiency and reduce copying.

In fact, there is another possibility,

What if someone does something like this: d1 = d1 calls itself?

So we'd better add a little judgment to this code:

#include <iostream>
using namespace std;

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

	// d1 = d2
	Date operator=(const Date& x) {
		if (this == &x) { //如果是自己给自己赋值,就直接返回了
			_year = x._year;
			_month = x._month;
			_day = x._day;
		}
		return *this;
	}

	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2023, 1, 1);
	Date d2;

	//如果我们使用一个对象赋值一个对象,就会调用赋值运算符重载
	d1 = d2;
	d1 = d1;

	return 0;
}

If we don't implement the assignment overload function,

The compiler will generate one by default, and this default generated is the same as the rule of copy construction:

For members of built-in types, value copies or shallow copies are made;

For custom type members, its assignment assignment overload will be called.

Therefore, if it is an object that requires deep copying like a stack, we also need to implement assignment overloading ourselves.

Note here:

Assignment overloading cannot be overloaded globally, because it is a default member function,

If we don't implement it, the compiler will automatically implement it for us. If we write it globally,

It will conflict with the default generated.

Write at the end:

The above is the content of this article, thank you for reading.

If you feel that you have gained something, you can give the blogger a like .

If there are omissions or mistakes in the content of the article, please private message the blogger or point it out in the comment area~

Guess you like

Origin blog.csdn.net/Locky136/article/details/131469364