类和对象-C++运算符重载

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

一、加号运算符重载

编译器本身掌握了1+1=2、 2+2=4之类的运算(内置数据类型),但当两个自定义的数据类型需要进行相加运算时,编译器不知道怎么处理。

我们当然可以通过函数来实现自定义数据类型的相加

class Person
{
public:
	int m_A;
	int m_B;
};
Person p1;
p1.m_A = 10;
p2.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;

此时想实现两个person中A与B值的和,可以定义一个函数,其返回值为新的person:(其中this指针指向调用该函数的类中的成员变量)

Person PersonAddPerson(Person &p)
{
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}

对于相加函数的命名,每个人都各不相同。此时编译器为大家起了通用的名称,为:operator+ 函数的其他内容无需改变。
因此,当我们想使用此函数进行实际加法时:

Person p3 = p1.operator+(p2);

可以简化为

Person p3 = p1 + p2;

二、左移运算符重载

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

int a = 10;
cout << a << endl;

Person p;
p.m_A = 10;
p.m_B = 10;
cout<< p << endl;

编译器可以对a进行输出,但是不知道p如何输出,需要重载左移运算符类型。通常采用全局函数重载左移运算符(成员函数无法实现cout在左侧)。

ostream & operator<< (ostream &cout , Person &p)
{
	cout<<"m_A = "<<p.m_A <<"m_B = "<<p.m_B;
	return cout;
}

三、递增运算符重载

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

class MyInteger
{
public:
	MyInteger()
	{
	m_Num = 0;
	}
private:
	int n_Num;
}

我们希望让MyInteger类实现整型数据一样的操作,能够递增。首先实现前置递增:

//前置递增
	MyInteger& operator++()
	{
		m_Num++;
		return *this;
	}
	void test01()
	{
		MyInteger myint;
		cout << myint++ << endl;
	}

1、首先,cout << myint++ << endl是我们最终的目标语句,不同于重载左移运算符,左移运算符与cout及之后要输出的内容关联,因此不仅需要形参,还需要用全局函数来定义;
2、递增运算符可以写在局部函数中,需要递增的量与重载函数都在同一个类中,可以直接调用,因此不需要形参;
3、在进行完递增操作后要返回自身,因此return *this;
4、返回值用引用的形式接收原因是:当重叠递增运算符时,如++(++myint),如果没有返回引用,第一次++后得到的是一个新的类,两次++后再输出myint结果只进行了一次,因此要引用。

其次实现后置递增:

	MyInteger operator++(int)
	{
		MyInteger temp = *this;
		m_Num++;
		return temp;
	}

1、后置递增与前置递增的区别是,后置递增会先返回原结果,再递增。因此我们要先返回输入时的结果,再进行递增操作。但又不能先return,这样函数会直接停止运行。因此,我们先定义一个类的实例来保存输入时的结果,在递增,再return。
2、此时不能用引用的形式来返回,因为引用作返回值时返回的不能是局部变量(局部变量保存在栈区,在函数结束后销毁),而返回值temp就是局部变量。因此这里直接返回值,不用引用。

四、赋值运算符重载

C++编译器至少给一个类添加4个函数:
1、默认构造函数
2、默认析构函数
3、默认拷贝构造函数
4、赋值运算符operator=,对属性进行值拷贝
对属性进行值拷贝与默认拷贝构造函数遇到的问题相似,也会出现深浅拷贝的问题,堆区内存重复释放。
在这里插入图片描述
解决方案:利用深拷贝解决浅拷贝带来的问题,因此要重写等号赋值运算。

//重载赋值运算符
	Person& operator=(Person& p)
	{
		if (m_Age != NULL);
		{
			delete m_Age;
			m_Age = NULL;
		}
		m_Age = new int(*p.m_Age);
		return *this;
	}

1、不同于之前学过的深浅拷贝,此时是进行赋值操作,在赋值前被赋值的类可能已经有值,因此要先判断属性是否为空,如果不为空先释放内存,再进行赋值。
2、等同于之前学过的深浅拷贝,将赋值的堆区内容解引用,重新开辟一块内存,在赋值给被赋值的对象。
3、想要实现连续赋值,返回值就必须还是自身,因此return *this。

五、关系运算符重载

作用:重载关系运算符,可以让两个自定义类型对象进行对比操作。
在这里插入图片描述
自定义的两个数据类型无法进行直接比较,需要重载关系运算符。


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


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

六、函数调用运算符重载

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

class MyPrint
{
public:
	//重载函数调用运算符
	void operator()(string test)
	{
		cout << test << endl;
	}
};

void test01()
{
	MyPrint myprint;
	myprint("Hello World!");
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值