C++学习笔记之运算符重载

数声风笛离亭晚,君向潇湘我向秦。


运算符重载

由于运算符只能实现一些内置数据类型的运算,而无法对自定义数据类型进行运算,对目前已有的运算符进行重新定义,以拓展其功能。

加法运算符重载

加法运算符重载有全局函数和局部函数两种实现方式,下面的代码重新编写了加法运算符函数重载加法运算符,将两个自定义类Person的的两个属性number1,number2相加,返回属性相加后的Person类。

函数名称使用编译器通用名称operator+命名重载加法运算符函数,可以将函数调用(p1.operator(p1)和p1.operator(p1.p2))简化为p1+p2的形式。

//局部函数实现+运算符重载
#include <iostream>
using namespace std;
class  Person
{
public:
	int number1;
	int number2;

	Person operator+(const Person& p)
	{
		Person temp;
		temp.number1 = this->number1 + p.number1;
		temp.number2 = this->number2 + p.number2;
		return temp;
	}
};
void printPerson(Person p1)
{
	cout << "数值1为" << p1.number1 << endl;
	cout << "数值2为" << p1.number2 << endl;
}

int  main()
{
	Person p1;
	p1.number1 = 10;
	p1.number2 = 20;
	Person p2;
	p2.number1 = 10;
	p2.number2 = 20;
	Person p3 = p1 + p2;//相当于p1.operaor+(p2)
	printPerson(p3);
	system("pause");
	return 0;	
}
//全局函数实现+运算符重载
#include <iostream>
using namespace std;
class  Person
{
public:
	
	Person(int a, int b) :number1(a), number2(b) {};//初始化列表
public:
	int number1;
	int number2;

};


Person operator+(Person& p1, Person& p2)
{
	Person p3(0,0);
	p3.number1 = p1.number1 + p2.number1;
	p3.number2= p1.number2 + p2.number2;
	return p3;
}
void printPerson(Person p1)
{
	cout << "数值1为" << p1.number1 << endl;
	cout << "数值2为" << p1.number2 << endl;
}

int  main()
{
	Person p1(10, 20);
	Person p2(10, 20);
	Person p3 = p1 + p2;//p1.operaor+(p1,p2)
	printPerson(p3);
	
}

左移运算符重载

重载左移运算符,cout<<加自定义类Person,可以打印Person的属性。

这里只能使用全局函数重载,是因为如果使用局部函数重载,只能实现<<cout效果,而不能实现cout<<。

#include <iostream>
using namespace std;
class Person
{
public:
	int number1;
	int number2;
	Person(int a, int b) : number1(a), number2(b) {};//初始化列表
};
//输出流对象cout只能有一个,所以传参跟返回值都需要使用引用
//全局函数重载左移运算符
ostream & operator<<(ostream & out, Person & p)
{
	cout << "number1=" << p.number1 << endl;
	cout << "number2=" << p.number2 << endl;
	return out;
}
void test()
{
	Person p1(10, 20);
	cout << p1 << endl;//使用了链式编程的思想,即同一个对象上通过多个方法的调用链实现一系列操作,根据其后参数的不同,前一个<<使用重载<<的定义,后一个<<使用原有的定义。
}
int main()
{
	test();
	system("pause");
	return 0;
}

递增运算符重载

重载递增运算符,自定义类Person++,++Person,可以实现类属性的递加。

#include <iostream>
using namespace std;
class Person
{
public:
	int number1 = 0;
	//前置++返回值为对象,由于是在类内的局部函数,对类内属性进行++,所以不需要传入其他参数
	Person& operator++()
	{
		number1++;
		return  *this;
	}
	//后置++返回值为数值,同一作用域下返回值不同不满足函数重载的条件,所以通过前置占位参数int来区分重载前置++和后置++函数,此处只能用int
//只要在重载操作符的参数中加上一个整数型参数,编译器就会自动将这个函数标示为后置,相应的不加则是前置
	int  operator++(int)
	{
		int temp = number1;
		number1++;
		return temp;
	}
};

ostream & operator<<(ostream & out, Person & p)
{
	cout <<p.number1;
	return out;
}
void test1()
{
	Person p1;
	cout << p1++ << endl;
	cout << p1 << endl;
	
}
void test2()
{
	Person p1;
	cout << ++p1 << endl;
	cout << p1 << endl;
}
int main()
{

	test1();
	test2();
	system("pause");
	return 0;
}

赋值运算符重载 

编译器提供的赋值运算符是浅拷贝,如果使用编译器提供的赋值运算符对两个自定义的类Person进行赋值运算p1=p2时,如果自定义对象有在堆区申请内存,则会导致堆区内存重复释放的问题。

重载赋值运算符,通过深拷贝来解决该问题。

#include <iostream>
using namespace std;
class Person
{
public:
	Person(int age)
	{
		m_age = new int(age);
	}

	int* m_age;
//返回引用是为了处理a=b=c的情况
	Person& operator=(Person& p)
	{
        //判断age是否为空,如果不为空,删除堆区申请的空间,并赋为空指针
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}
		//深拷贝,在堆区申请一块位置,并将传入的*p.m_age的值赋给它,同时另m_age指针等于它
		m_age = new int(*p.m_age);
		return *this;//返回自身
	}
	~Person()
	{
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}
	}
};

void test()
{
	Person p1(12);
	Person p2(13);
	Person p3(14);
	p1 = p2 = p3;//将p3的值赋给p2,再将p2的值赋给p1;
	cout << *p1.m_age << endl;
	cout << *p2.m_age << endl;
	cout << *p3.m_age << endl;
}
int main()
{
	test();
	system("pause");
	return 0;
}

关系运算符

重载关系运算符!=、==,比较两个Person类的属性是否相等。

#include <iostream>
using namespace std;
class Person
{
public:
	int m_number1;
	int m_number2;
	Person(int number1, int number2) :m_number1(number1), m_number2(number1) {};
};
bool operator!=(Person p1, Person p2)
{
	if (p1.m_number1 == p2.m_number1 && p1.m_number2 == p2.m_number2)
	{
		return false;
	}
	else
	{
		return true;
	}
}
bool operator==(Person p1, Person p2)
{
	if (p1.m_number1 == p2.m_number1 && p1.m_number2 == p2.m_number2)
	{
		return true;
	}
	else
	{
		return false;
	}
}


void test()
{
	Person p1(11, 12);
	Person p2(12, 13);
	Person p3(11, 12);
	if (p1 != p2)
	{
		cout << "p1不等于p2" << endl;
	}
	else
	{
		cout << "p1等于p2" << endl;
	}

	if (p1 == p3)
	{
		cout << "p1等于p3" << endl;
	}
	else
	{
		cout << "p1不等于p3" << endl;
	}

}
int main()
{
	test();
	system("pause");
	return 0;
}

函数调用运算符重载

函数调用运算符重载后的使用方式与函数调用相似,因此也被称为仿函数,仿函数十分灵活,参数数量、返回值类型都不固定,根据需求决定。

#include <iostream>
using namespace std;
class Person
{
public:

	int operator()(int number1,int number2)
	{
		return number1 + number2;
	}
};

void test()
{
	Person p1;
	int ret = p1(100, 200);
	cout<< ret<<endl;

}
int main()
{
	test();
	//匿名函数对象,不创建对象而通过匿名对象调用仿函数。Person()为匿名对象,当前行结束立即被释放。
	int ret1=Person()(100, 200);
	cout << ret1 << endl;
	system("pause");
	return 0;
}

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值