C++核心之类和对象——运算符重载P121-P126

4.5 运算符重载

运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

4.5.1 加号运算符重载

作用:实现两个自定义数据类型相加的运算

#include <iostream>
using namespace std;

//加号运算符重载

//1.成员函数重载
class Person
{
public:
	//成员函数实现 + 号运算符重载
	Person operator+(Person& p) {
		Person temp;
		temp.m_A = this->m_A + p.m_A;
		temp.m_B = this->m_B + p.m_B;
		return temp;
	}
public:
	int m_A;
	int m_B;

};

//2.全局函数重载+号
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+(const Person& p2, int num)
{
	Person temp;
	temp.m_A = p2.m_A + num;
	temp.m_B = p2.m_B + num;
	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 = p2.operator+(p1);
	//Person p3 = p1 + p2;

	cout << "p3.m_A=" << p3.m_A << endl;//20
	cout << "p3.m_B=" << p3.m_B << endl;//20

	//全局函数重载本质调用
	Person p4 = operator+(p1, p2);
	cout << "p4.m_A=" << p4.m_A << endl;//20
	cout << "p4.m_B=" << p4.m_B << endl;//20

	Person p5 = p1 + 100;//Person+int
	cout << "p5.m_A=" << p5.m_A << endl;//110
	cout << "p5.m_B=" << p5.m_B << endl;//110
}

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

总结1:对于内置的数据类型的表达式的运算符是不可能改变的

总结2:不要滥用运算符重载

4.5.2左移运算符重载

作用:可以输出自定义数据类型

#include <iostream>
using namespace std;

//左移运算符重载
class Person02
{
	friend ostream& operator<<(ostream& cout, Person02& p);
private:
	//1.利用成员函数重载左移运算符
	//成员函数 实现不了重载<<运算符,因为p.operator(cout) 简化成 p << cout 不是我们想要的效果
	//void operator<<(Person& p){
	//}
	int m_A;
	int m_B;	
public:
	Person02(int a,int b)
	{
		m_A = a;
		m_B = b;
	}
};
//只能利用全局函数重载左移运算符
//ostream 对象只能有一个
ostream& operator<<(ostream &cout, Person02 &p)//输出流只有一个,只能地址传递,而不能值传递也就是拷贝
{
	cout << "m_A=" << p.m_A << "m_B=" << p.m_B ;
	return cout;
}
void test02()
{
	Person02 p(10,10);

	cout << p<<"hello"<<endl;//链式编程
}
int main()
{
	test02();
	system("pause");
	return 0;
}

4.5.3递增运算符

作用: 通过重载递增运算符,实现自己的整型数据

#include <iostream>
using namespace std;

//自定义整型
class MyInteger
{
	friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
	MyInteger()
	{
		m_Num = 0;
	}
	//重载前置++运算符,返回引用为了一直对一个数据进行递增操作
	MyInteger& operator++()
	{
		//先进行++运算
		m_Num++;
		//再将自身返回
		return *this;
	}
	//重载后置++运算符,返回值
	//MyInteger& operator++(int) int代表占位参数 ,可以用来区分前置和后置
	MyInteger operator++(int)
	{
		//先记录当时的结果
		MyInteger temp = *this;//temp是局部对象,所以返回的时候不能加引用
		//后 递增
		m_Num++;
		//最后将
		return temp;
	}

private:
	int m_Num;
};

//重载<<运算符
ostream& operator<<(ostream& cout, MyInteger myint)
{
	cout << myint.m_Num << endl;
	return cout;
}
void test03()
{
	MyInteger myint;
	cout << ++(++myint) << endl;//2
	cout << myint << endl;//2
}

void test04()
{
	MyInteger myInt;
	
	cout << myInt++ << endl;//0
	cout << myInt << endl;//1
}
int main()
{
	test03();
	test04();
	system("pause");
	return 0;
}

总结: 前置递增返回引用,后置递增返回值
课后作业:递减运算符重载

4.5.4 赋值运算符重载

c++编译器至少给一个类添加4个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对属性进行值拷贝
4.赋值运算符 operator=, 对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

#include <iostream>
using namespace std;

class Person04
{
public:
	Person04(int age)
	{
		m_age = new int(age);
	}
	~Person04()
	{
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}
	}

	//重载赋值运算符
	Person04& operator=(Person04 &p)
	{
		//编译器是提供浅拷贝
		//m_age=p.m_age;

		//应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}

		//深拷贝
		m_age = new int(*p.m_age);
		//返回对象的本身
		return *this;
	}
	int* m_age;
};
void test05()
{
	Person04 p1(18);
	Person04 p2(20);
	Person04 p3(30);

	cout << "p1的年龄为:" << *p1.m_age << endl;
	cout << "p2的年龄为:" << *p2.m_age << endl;

	//p2 = p1;//赋值操作

	p3 = p2 = p1;
	cout << "p1的年龄为:" << *p1.m_age << endl;//18
	cout << "p2的年龄为:" << *p2.m_age << endl;//18
	cout << "p3的年龄为:" << *p3.m_age << endl;//18
}
int main()
{
	test05();
	system("pause");
	return 0;
}

4.5.5 关系运算符重载

作用: 重载关系运算符,可以让两个自定义类型对象进行对比操作

#include <iostream>
using namespace std;

class Person05
{
public:
	Person05(string name, int age)
	{
		m_name = name;
		m_age = age;
	}
	//重载==
	bool operator==(Person05 &p)
	{
		if ((this->m_age == p.m_age) && (this->m_name == p.m_name))
		{
			return true;
		}
		else
			return false;
	}
	//重载!=
	bool operator!=(Person05 &p)
	{
		if ((this->m_age != p.m_age) || (this->m_name != p.m_name))
		{
			return true;
		}
		else
			return false;
	}
	string m_name;
	int m_age;
};
void test06()
{
	Person05 p1("Tom",18);
	Person05 p2("Tom",18);
	Person05 p3("Jerry", 18);

	if (p1 == p2)
	{
		cout << "p1和p2相等" << endl;
	}
	if (p1 != p3)
	{
		cout << "p1和p3是不相等" << endl;
	}
	else
	{
		cout << "p1和p3相等" << endl;
	}
}
int main()
{
	test06();
	system("pause");
	return 0;
}

运行结果:在这里插入图片描述

4.5.6 函数调用运算符重载

  • 函数调用运算符 () 也可以重载
  • 由于重载后使用的方式非常像函数的调用,因此称为仿函数
  • 仿函数没有固定写法,非常灵活
#include <iostream>
using namespace std;

//函数调用运算符重载

//打印输出类
class Myprint
{
public:
	//重载函数调用运算符
	void operator()(string text)
	{
		cout << text << endl;
	}
};
void print(string text)
{
	cout << text << endl;
}
void test07()
{
	Myprint myprint;
	myprint("helloworld");//由于使用起来非常类似与函数调用,所以称为仿函数
	print("helloworld");
}
//仿函数非常灵活,没有固定的写法
//加法类
class Myadd
{
public:
	int operator()(int num1,int num2)
	{
		return num1 + num2;
	}
};
void test08()
{
	Myadd myadd;
	int ret = myadd(100, 200);
	cout << "ret=" << ret << endl;

	//匿名函数对象
	cout << Myadd()(100, 300) << endl;//其中Myadd()是创建了一个匿名对象
}
int main()
{
	test07();
	test08();

	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值