运算符重载概念:对已有运算符重新定义,赋予其另一种功能,以适应不同的数据类型。
作用:实现两个自定义数据类型相加的运算。
目录
加号运算符重载
1.成员函数重载+
2.全局函数重载+
左移运算符重载<<
递增运算符重载
赋值运算符重载
关系运算符重载
函数调用运算符重载
加号运算符重载
1.成员函数重载+

#include<iostream>
#include<string>
using namespace std;
//加号运算符重载
class person
{
public:
	//1.成员函数重载+
	person operator + (person &p)//传入一个person类
	{
		person temp;
		temp.m_a = this->m_a + p.m_a;
		temp.m_b = this->m_b + p.m_b;
		return temp;
	}
	int m_a;
	int m_b;
};
void test01()
{
	person p1;
	p1.m_a = 10;
	p1.m_b = 10;
	person p2;
	p2.m_a = 10;
	p2.m_b = 10;
	person p3 = p1 + p2;
	cout << p3.m_a << " " << p3.m_b;
}
int main()
{
	test01();
	system("pause");
	return 0;
}2.全局函数重载+
#include<iostream>
#include<string>
using namespace std;
//加号运算符重载
class person
{
public:
	int m_a;
	int m_b;
};
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 = 10;
	p2.m_b = 10;
	person p3 = p1 + p2;
	cout << p3.m_a << " " << p3.m_b;
}
//2.全局函数重载+
int main()
{
	test01();
	system("pause");
	return 0;
}	//成员函数重载本质调用
	person p3 = p1.operator +(p2);
	//全局函数重载本质调用
	person p3 = operator+(p1, p2);
    //简化版
    person p3=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;
}
person operator +(person& p1, int num)
{
	person temp;
	temp.m_a = p1.m_a + num;
	temp.m_b = p1.m_b + num;
	return temp;
}总结1:对于内置的数据的表达式运算符是不可能改变的
//最好只改变自定义类型表达式运算符
总结2:不要滥用运算符重载
左移运算符重载<<
作用:可以输出自定义的数据类型
#include<iostream>
#include<string>
using namespace std;
//左移运算符重载
class person
{
public:
	
	int m_a;
	int m_b;
};
//只能利用全局函数重载左移运算符
ostream& operator<<(ostream& nixx, person& p)
{//本质  operator<<(cout,p) ,简化   cout<<p
	nixx << p.m_a << " " << p.m_b ;
	return nixx;
}
void test01()
{
	person p;
	p.m_a = 10;
	p.m_b = 10;
	cout << p<<"    i want to play LOL"<<endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}递增运算符重载
作用:通过重载递增运算符,实现自己的整型数据
	//重载++运算符,++a
	myinteger& operator++()//如果返回 值,myint就只能进行一次递增
	{
		m_num++;
		return *this;//返回自身
	}	myinteger operator++(int)//int代表一个占位参数,可以用于区分前置和后置递增
	{
		//先记录当时结果
		myinteger temp = *this;
		//后  递增
		m_num++;
		//最后将记录结果做返回
		return temp;
	}#include<iostream>
#include<string>
using namespace std;
//重载递增运算符
// 
//自定义整型
class myinteger
{
	friend ostream& operator<<(ostream& cout, myinteger myint);
public:
	myinteger()
	{
		m_num = 0;
	}
	//重载++运算符,++a
	myinteger& operator++()//如果返回 值,myint就只能进行一次递增
	{
		m_num++;
		return *this;//返回自身
	}
	//重载++运算符,a++
	//后置递增一定要返回值
	myinteger operator++(int)//int代表一个占位参数,可以用于区分前置和后置递增
	{
		//先记录当时结果
		myinteger temp = *this;
		//后  递增
		m_num++;
		//最后将记录结果做返回
		return temp;
	}
private:
	int m_num;
};
ostream& operator<<(ostream& cout, myinteger myint)
{
	cout << myint.m_num;
	return cout;
}
void test01()
{
	myinteger myint;
	cout << ++myint << endl;
	cout << myint << endl;
}
void test02()
{
	myinteger myint;
	cout << myint++ << endl;;
	cout << myint << endl;
}
int main()
{
	//test01();
	test02();
	system("pause");
	return 0;
}要注意,前置递增是返回引用,后置递增则返回值。
同时后置递增时,左移运算符重载时要把()里的第二个参数的&去掉。
并且,由于这一点,后置递增不适用于链式编程。
练习了一下递减运算符重载,理解了就很好敲。
#include<iostream>
#include<string>
using namespace std;
class myinteger
{
	friend ostream& operator << (ostream& cout, myinteger myint);
public:
	myinteger()
	{
		m_num = 8;
	}
	myinteger& operator--()
	{
		this->m_num--;
		return *this;//返回自身
	}
	myinteger operator--(int)
	{
		myinteger temp = *this;
		this->m_num--;
		return temp;//返回自身
	}
private:
	int m_num;
};
ostream& operator << (ostream & cout, myinteger  myint)
{
	cout << myint.m_num;
	return cout;
}
void test01()
{
	myinteger myint;
	cout << --myint << endl;
}
void test02()
{
	myinteger myint;
	cout << myint-- << endl;
	cout << myint << endl;
}
int main()
{
	//test01();
	test02();
	system("pause");
	return 0;
}赋值运算符重载
C++编译器至少给一个类添加4个函数
1.默认构造函数(无参,函数体为空
2.默认析构函数(无参,函数体为空
3.默认拷贝函数,对属性进行值拷贝
4.赋值运算符 operator=,对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题
#include<iostream>
#include<string>
using namespace std;
//赋值运算符重载
class person
{
public:
	person(int age)
	{
		m_age = new int(age);//把数据创建在堆区,并且用指针指向
	}
	//堆区数据需要我们手动开辟,手动释放
	//要提供析构函数,把数据释放干净
	~person()
	{
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}
	}
	person& operator=(person&p)
	{
		//应该先判断是否有属性在堆区,要先释放干净,再进行深拷贝
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}
		m_age = new int(*p.m_age);//深拷贝
		return *this;
	}
	int *m_age;//把年龄用指针,而其真实数据要开辟到堆区
};
void test01()
{
	person p1(18);
	person p2(20);
	person p3(30);
	p3 = p2 = p1;//赋值运算,简单的浅拷贝
	//指向同一块内存,导致后续内存重复释放,因此我们要利用深拷贝解决浅拷贝带来的问题
	cout << *p1.m_age<<endl;
	cout << *p2.m_age << endl;
	cout << *p3.m_age << endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}关系运算符重载
这个比起上面简直是小巫见大巫~~
#include<iostream>
#include<string>
using namespace std;
//关系运算符重载
class person
{
public:
	person(string name, int age)
	{
		m_name = name;
		m_age = age;
	}
	bool operator==(person& p)
	{
		if (this->m_name == p.m_name && this->m_age == p.m_age)
		{
			return true;
		}
		return false;
	}
	string m_name;
	int m_age;
};
void test01()
{
	person p1("胡图图",3);
	person p2("胡英俊", 3);
	if (p1 == p2)
	{
		cout << "same" << endl;
	}
	else cout << "different" << endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}函数调用运算符重载
函数调用运算符()也可以重载
由于重载后使用的方式非常像函数的调用,因此称为仿函数
仿函数没有固定写法,非常灵活
#include<iostream>
#include<string>
using namespace std;
//函数调用运算符重载
class myprint
{
public:
	//重载函数调用运算符
	void operator()(string test)
	{
		cout << test << endl;
	}
	
};
class myadd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}
};
void test01()
{
	myprint print;
	print("hello hututu");
	myadd add;
	cout<<add(78, 98)<<endl;
	//匿名函数对象
	cout << myadd()(100, 100) << endl;//即不先创建一个myadd类,匿名对象执行完立即释放
	//通过一个类型和()会创建一个匿名对象
}
int main()
{
	test01();
	system("pause");
	return 0;
}


















