C + + operator overloading

Keywords: C++

C + + operator overloading

Operator overloading concept: redefine the existing operators and give them another function to adapt to different data types

Operator overloading can also occur

1. The plus sign operator (+) is overloaded

Function: realize the operation of adding two user-defined data types

code implementation

#include <iostream>
using namespace std;

class Person {
public:
	//1. Member function overload + sign, and the essential call is Person p3 = p1.operator+(p2);
	Person operator+(Person& p)
	{
		Person temp;
		temp.m_A = this->m_A + p.m_A;
		temp.m_B = this->m_A + p.m_B;
		return temp;
	}

	int m_A;
	int m_B;
};

//2. Global function overload + sign, and the essential call is Person p3 = operator+(p1,p2);
//Person operator+(Person &p1, Person &p2)
//{
//	Person temp;
//	temp.m_A = p1.m_A + p2.m_A;
//	temp.m_B = p1.m_B + p2.m_B;
//	return temp;
//}

void test01()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;
	Person p2;
	p2.m_A = 20;
	p2.m_B = 20;

	Person p3 = p1 + p2;
	cout << "p3.m_A= " << p3.m_A << endl;
	cout << "p3.m_B= " << p3.m_B << endl;
}

int main()
{
	test01();
	return 0;
}

2. Shift left operator (cout) overload

Function: you can output custom data types

code implementation

#include <iostream>
using namespace std;

class Person {
public:
	//Usually, we will not overload the shift left operator with member functions, because cout cannot be implemented on the left, so we have to write P < < cout when calling


	int m_A;
	int m_B;
};

//Overloading shift left operator with global function
ostream& operator<<(ostream& cout, Person& p)
{
	cout << "p.m_A= " << p.m_A << endl;
	cout << "p.m_B= " << p.m_B << endl;
	return cout;
}

int main()
{
	Person p;
	p.m_A = 10;
	p.m_B = 10;

	cout << p << endl;
	return 0;
}
  • If you need to output private content in the class, remember to set the overloaded function as a friend

  • Set the output type of overloaded function cout to ostream, and other output values can be added after the function, such as cout < < p < < Hello World < < endl;

3. Increment operator (+ +) overload

Function: overload the increment operator to realize the increment of their own shaping data. But for the same reason, you can also write a decrement operator overload

code implementation

#include <iostream>
using namespace std;

class MyInteger
{
public:
	MyInteger()
	{
		m_Num = 10;
	}

	//Overload leading + + operator (+ + i)
	MyInteger &operator++()
	{
		++m_Num;
		return *this;		//Return the class itself
	}

	//Overload post + + operator (i + +)
    //Because the function returns the local variable temp, the local variable will be released after the function is called, so the function can only return a value, not a reference&
	MyInteger operator++(int)	//int represents a placeholder parameter, which is used to distinguish between pre and post increment
	{
		MyInteger temp = *this;
		m_Num++;
		return temp;		//Return the class itself
	}

	int m_Num;
};

ostream &operator<<(ostream &cout, MyInteger &myint)
{
	cout << myint.m_Num;
	return cout;
}

int main()
{
	MyInteger myint;
	cout << ++myint << endl;
	return 0;
}

Increment operators are divided into pre increment (+ + i) and post increment (i + +), which are written as follows:

  • Overload leading increment operator:

    Function return value & operator + + ();

  • Overload post increment operator:

    Function return value operator++(int);

be careful:

(1) . overloaded pre operator does not need to pass in a parameter, while overloaded post operator needs to pass in a placeholder parameter int;

(2) . the overloaded pre operator returns a reference, and subsequent chain calls can be continued on the value; Overloaded post operators directly return the value of local variables. Because local variables are released after function calls, an error will be reported if a local variable address is referenced.

4. Overload of assignment operator (=)

The C + + compiler adds at least four default functions to one class:

  1. Default constructor (no parameters)
  2. Default destructor (no parameters)
  3. The default copy constructor makes a shallow copy of the attribute
  4. The assignment operator operator =, copies the value of the attribute

As long as the problem of value copying is involved, it is necessary to find out whether it is a deep copy (the copy object and the original object point to different storage spaces) or a shallow copy (the copy object and the original object point to the same storage space, which may lead to release problems)

code implementation

#include <iostream>
using namespace std;

class Person {
public:
	int *m_Age;

	Person(int age)	
	{
		m_Age = new int(age);
	}

	~Person()		//The destructor is written to make it easy to see the difference between shallow copy and deep copy
	{
		if (m_Age) {
			delete m_Age;
			m_Age = NULL;
		}
	}

	Person &operator=(Person& p)
	{
		//First judge whether there are attributes in the heap area. If so, release them clean first, and then deep copy them
		if (m_Age)
		{
			delete m_Age;
			m_Age = NULL;
		}
		//Deep copy
		m_Age = new int(* p.m_Age);
		
		//The compiler only provides the following shallow copies:
		//m_Age = p.m_Age;

		return *this;
	}
};

void test()
{
	Person p1(10);
	Person p2(20);

	p2 = p1;		//Assignment operation, call overloaded function

	cout << "p1.m_Age= " << *p1.m_Age << endl;
	cout << "p2.m_Age= " << *p2.m_Age << endl;
}

int main()
{
	test();
	return 0;
}

5. Overloading of relational operator (= =)

During the comparison operation, if the member values in the two classes need to be compared, we need to overload the equivalence operator and select the members to be compared.

code implementation

#include <iostream>
using namespace std;

class Person {
public:
	string m_Name;
	int m_Age;

	Person(string name, int age)		//Parameterized constructor
	{
		m_Name = name;
		m_Age = age;
	}

	bool operator==(Person& p)		//Equivalence operator overload
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
			return true;
		}
		else {
			return false;
		}
	}

};

int main()
{
	Person p1("Zhang San",10);
	Person p2("Li Si", 20);
	if (p1 == p2) {
		cout << "p1 and p2 equal" << endl;
	}
	else {
		cout << "p1 and p2 Unequal" << endl;
	}
	return 0;
}

For the same reason, it can also be overloaded= Operator, less than < operator, greater than > operator, etc.

6. Function call operator () overload

Yes, what is overloaded here is a pair of parentheses ()

  • Because the method used after overloading is more like the call of a function, it is also called imitation function. Imitation function has no fixed writing method and is very flexible

code implementation

#include <iostream>
using namespace std;

class MyPrint
{
public:
	void operator()(string str)
	{
		cout << str << endl;
	}
};

int main()
{
	MyPrint myprint;

	myprint("hello world!");		//The () here uses an overloaded function, which itself is like a function

	return 0;
}

In the above code, () is overloaded as an output function. As an imitation function, it can realize various functions. Almost all the previous overload types can be overloaded with calling operators (I guess I didn't test it). Pay attention not to be confused in later use.

Posted by sandeep251088 on Sat, 30 Oct 2021 01:11:08 -0700