【C++入门篇 - 6】:运算符重载

运算符重载


运算符重载的概念

  1. 重载,重新载入,就比如之前那讲的函数重载,对一个已有的函数赋值一个新的定义,因此同一个名字就可以有不同的含义。
  2. 运算符也是可以重载的,比如cout在输出一个变量的时候,能接收不同类型的数据并输出,他就是重载了<<运算符,这个就是运算符重载。
  3. 所以运算符指的是对已有的运算符重新定义新的运算规则,已适应不同的数据类型,当然重载之后之前的运算规则还是有的。

运算符重载示例

  1. 几乎所有的运算符都可以被重载
  2. 运算符重载基本出现在类中和结构体中
  3. 运算符可以理解为函数的一个表现

语法

  • 关键字:operator
  • 函数返回值 operator运算符(参数列表)

下面举一个简单的例子:重载+运算符
+运算符的特性:是双目运算符,两操作数操作完之后不改变任何一个操作数,把结果返回出去

对以下代码的重要部分进行讲解:
MyPoint MyPoint::operator+(MyPoint const&srcPoint) const;

&(引用):调用重载+运算符会发生值拷贝,基于本例,会拷贝八字节,所以使用引用优化拷贝过程:原本拷贝八字节,使用引用后变为四字节。
const:第一个const用来消除引用的弊端(引用有个弊端,在函数体内就可以修改它的值,根据+运算符的特性,不能修改其值,所以我们加上const)
第二个const将函数变为常量函数,使用本身不能被修改。

#include<iostream>

class MyPoint
{
	int x, y;
public:
	MyPoint(int x, int y);
	//+运算符的特性:是双目运算符,两操作数操作完之后不改变任何一个操作数,把结果返回出去
	MyPoint operator+(MyPoint const& srcPoint) const; //+运算符重载定义示例
};

MyPoint::MyPoint(int x, int y)
{
	this->x = x;
	this->y = y;
}

MyPoint MyPoint::operator+(MyPoint const&srcPoint) const
{
	MyPoint tempPoint(0, 0);
	tempPoint = *this; //*this表示调用者对象,谁调用+,就把它赋给tempPoint
	tempPoint.x += srcPoint.x;
	tempPoint.y += srcPoint.y;
	return tempPoint;
}

void main()
{
	MyPoint m1(1, 1);
	MyPoint m2(2, 2);
	MyPoint m3(0, 0);
	m3 = m1 + m2; //运算符重载的显示调用
	m3 = m1.operator+(m2); //和上面的调用等效
}

在这里插入图片描述

运算符重载的特殊示例

  1. 重载运算符,这个重载的运算符还是满足原来的规则,不能说重载+,结果做的是-的事,这样会使在运算符重载的运用上增加很大的难度。
  2. 运算符重载的参数,类中重载调用对象会占一个参数,就是this会占一个参,参数列表就是用来表示运算符的操作数的。
  3. 对于运算符重载的调用,可以直接使用运算符,也可以通过对象出来调用。
  4. 考虑返回值,不同的运算符有不同的返回值,要记得满足运算符原来的规则。

赋值运算符的重载

#include<string.h>
class MyString
{
	char *pStr;
	int len;
public:
	MyString();
	MyString(char *str);
	MyString(MyString const&other); //拷贝构造
	~MyString();
public:
	MyString operator+(MyString const& srcStr) const;
};

MyString::MyString() //构造函数
{
	pStr = NULL;
	len = 0;
}

MyString::~MyString() //析构函数
{
	if (pStr)
	{
		delete[]pStr;
		pStr = NULL;
	}
}

MyString::MyString(MyString const&other) //拷贝构造函数
{
	pStr = NULL;
	len = other.len;
	if (len != 0)
	{
		pStr = new char[len];
		strcpy(pStr, other.pStr);
	}
}

MyString::MyString(char *str)
{
	if (str == NULL)
	{
		pStr = NULL;
		len = 0;
	}
	else
	{
		len = strlen(str) + 1;
		if (len != 0)
		{
			pStr = new char[len];
			strcpy(pStr, str);
		}
	}
}

MyString MyString::operator+(MyString const& srcStr) const //重载+运算符
{
	MyString tempStr;
	tempStr.len = len + srcStr.len - 1;
	tempStr.pStr = new char[tempStr.len];
	strcpy(tempStr.pStr, pStr);
	strcat(tempStr.pStr, srcStr.pStr);
	return tempStr;
}
void main()
{
	MyString m1("1234");
	MyString m2("ABCD");
	MyString m3 = m1 + m2; //调用拷贝构造
	MyString m4;
	m4 = m1 + m2; //调用赋值运算符给m4赋值
	int c = 0;
}
  • 通过调试以上代码,发现报错,报错的原因是赋值运算符没有进行重载。
    在这里插入图片描述
  • 对赋值运算符进行重载。注意:如果没有书写重载赋值运算符,系统会提供一个有操作的赋值运算符操作,如果有堆内存的操作,必须重写赋值运算符的操作。
  • 在声明中,因为赋值运算符的特性是会改变调用者对象,所以不能使用常量函数,而且会返回调用者自身,所以使用第一个引用。
    在这里插入图片描述
  • 重载赋值运算符的代码
MyString& MyString::operator=(MyString const& srcStr)
{
	//在赋值之前不确定自己的堆内存有没有数据
	if (pStr != NULL)
	{
		delete[]pStr;
	}
	pStr = NULL;
	len = srcStr.len;
	if (len != 0)
	{
		pStr = new char[len];
		strcpy(pStr, srcStr.pStr);
	}
	return *this; //返回调用者自身
}

在这里插入图片描述

自增运算符的重载

本次示例是基于以上代码,对 前置++ 和 后置++ 运算符进行重载。

在这里插入图片描述

  • 前置++和后置++重载的代码如下
MyString MyString::operator++(int)
{
	MyString tempStr = *this; //先报错自身改变之前的值
	for (int i = 0; i < len - 1; ++i) // 自身改变
	{
		(*(pStr + i))++;
	}
	return tempStr; //返回改变前的值
}

MyString& MyString::operator++()
{
	for (int i = 0; i < len - 1; ++i)
	{
		(*(pStr + i))++;
	}
	return *this;
}

在这里插入图片描述

使用友元重载函数

类在已经实现且部分修改的情况下,需要进行运算符重载就可以通过友元的方式来进行重载。

例1:使用友元重载+运算符(基于以上示例)
当在运算符重载里做两个数的相加,它不属于任何对象,就给它做成友元函数。
友元不属于类和对象,所以几目就几个参数。

//这里只贴出部分代码,MyString是一个类
friend MyString operator+(MyString const&srcStr1, MyString const& srcStr2)
{
	MyString tempStr;
	tempStr.len = srcStr1.len + srcStr2.len - 1;
	tempStr.pStr = new char[tempStr.len];
	strcpy(tempStr.pStr, srcStr1.pStr);
	strcat(tempStr.pStr, srcStr2.pStr);
	return tempStr;
}

例2:输入、输出的重载

  • 没有进行重载前,使用cin或cout时报错
    在这里插入图片描述

  • 对输入输出进行重载
    在这里插入图片描述

istream& operator>>(istream &is, MyString& str)
{
	char tempArr[1024] = {};
	is >> tempArr;
	if (str.pStr != NULL)
	{
		delete[]str.pStr;
	}
	str.len = strlen(tempArr) + 1;
	str.pStr = new char[str.len];
	strcpy(str.pStr, tempArr);
	return is;
}

ostream& operator<<(ostream&os, MyString const& str)
{
	os << str.pStr;
	return os;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

街 三 仔

你的鼓励是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值