C++ 运算符重载

运算符重载

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

加号运算符重载

  • 作用:实现两个自定义数据类型相加的运算
  • 1、成员函数重载 + 号
    成员函数重载本质调用:
person p3 = p1.operator+(p2);
  • 2、全局函数重载 + 号
    全局函数重载本质调用:
person p3 = operator+(p1,p2);
#include <iostream>
using namespace std;

class person {
public:
	//1、成员函数实现 + 号运算符重载 
	/*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;
	}*/
	int m_a;
	int m_b;
};
//2、全局函数实现 + 号运算符重载 
person operator+(const person& p1, const 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;
}
void test() {
	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;
	//运算符重载也可以用于函数重载
	person p4 = p1 + 100;//person + int
	cout << "p4.m_a = " << p4.m_a << endl;
	cout << "p4.m_b = " << p4.m_b << endl;
}
int main(void)
{
	test();
	return 0;
}

总结:
1、对于内置的数据类型的表达式的运算符是不可能发生改变的。
2、不要滥用运算符重载。


左移运算符重载

1、一般不用成员函数实现左移运算符重载,因为它不能将变量置于<<符号的右边。
2、全局函数可以实现左移运算符的重载。

#include <iostream>
using namespace std;
class person {
	friend ostream& operator<<(ostream& out, person& p);//友元的应用
public:
	person(int a, int b)
	{
		this->m_a = a;
		this->m_b = b;
	}
private:
	int m_a;
	int m_b;
};
//全局函数实现左移重载,ostream对象只能有一个
ostream& operator<<(ostream & out, person & p)//cout为ostream类型
{
	out << "a:" << p.m_a << " b:" << p.m_b << " ";
	return out;//有返回值以便实现链式编程
}
void test()
{
	person p1(10,20);
	cout << p1 << "hello world" << endl;//可以直接输出对象,链式编程
}
int main(void)
{
	test();
	return 0;
}

总结:重载左移运算符配合友元可以实现输出自定义数据类型。


递增运算符重载

  • 作用:通过重载递增运算符,实现自己的整形数据。
#include <iostream>
using namespace std;
class myintger{
public:
	friend ostream& operator<<(ostream& cout, myintger p);//应用友元
		myintger() {
		 m_num = 0;
	}
		//重载前置++运算符,返回引用为了一直对一个数据进行递增
		//如果不返回引用则会在下次使用++运算符时对新的对象进行操作,导致++失败。
		myintger& operator++() {
			m_num++;//先进行++运算
			return *this;//再将自身做返回
		}
		//重载后置++运算符
		myintger operator++(int){//使用占位参数来达到函数重载的目的
			myintger temp = *this;//先记录当时结果
			m_num++;//后递增
			return temp;//最后将记录结果返回
			//此处返回的是局部对象,当前操作执行完即被释放。后面再返回则会是非法操作。
		}
	private:
		int m_num;
};
ostream& operator<<(ostream& cout,myintger p){//重载左移运算符
	cout << p.m_num;
	return cout;
}
void test()
{
	myintger p;
	myintger p1;
	cout << ++(++p) << endl;//2
	cout << p << endl;//2
	cout << p1++ << endl;//0
	cout << p1 << endl;//1
}
int main(void)
{
	test();
	return 0;
}

总结:前置递增返回引用,后置递增返回值。


赋值运算符重载

C++编译器至少给一个类添加4个函数
1、默认构造函数(无参,函数体为空)
2、默认析构函数(无参,函数体为空)
3、默认拷贝构造函数,对属性进行值拷贝。
4、赋值运算符operator=,对属性进行值拷贝。

  • 注意:如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题。
#include <iostream>
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)//重载赋值运算符
		//编译器提供的代码是浅拷贝
		//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 test()
{
	person p1(18);
	person p2(20);
	person p3(30);
	p3 = p2 = p1;//赋值操作
	cout << "p1的年龄为:" << *p1.m_age << endl;
	cout << "p2的年龄为:" << *p2.m_age << endl;
	cout << "p3的年龄为:" << *p3.m_age << endl;
}
int main(void)
{
	test();
	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_age == p.m_age && this->m_name == p.m_name) {
			return true;
		}
		else {
			return false;
		}
	}
	string m_name;
	int m_age;
};
void test()
{
	person p1("Tom",18);
	person p2("Jerry", 19);
	if (p1 == p2) {
		cout << "p1和p2是相等的";
	}
	else {
		cout << "p1和p2是不相等的";
	}
}
int main(void)
{
	test();
	return 0;
}

函数调用运算符重载

1、函数调用运算符()也可以重载。
2、由于重载后使用的方式非常像函数的调用,因此称为仿函数
3、仿函数没有固定的写法,非常灵活。

#include <iostream>
#include <string>
using namespace std;
class Myprint {//输出字符串
public:
	void operator()(string text) {//重载()运算符,也称作仿函数。
		cout << text << endl;
	}
};
class Myadd {//两数相加,仿函数非常灵活,没有固定的格式
public:
	int operator()(int a, int b) {
		return a + b;
	}
};
void test()
{
	Myprint print;
	print("Hello world");
	Myadd myadd;
	int ret = myadd(10, 20);
	cout << "ret = " << ret << endl;
	//匿名对象调用
	cout << "Myadd()(100,100) = " << Myadd()(100, 100) << endl;
}
int main(void)
{
	test();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值