关于运算符重载的总结


一、讲在前面

大家好,我讲一下运算符的重载

二、关于友元的补充

在讲运算符重载之前,先补充一下友元的知识

类可以允许其他类或者函数访问它的非公有成员,方法是令其他类或者函数成为他的友元(friend)。如果类想把一个函数作为他的友元,只需要增加一条以friend关键字开始的函数声明语句即可

友元声明只能出现在类定义的内部,但是在类内出现的具体位置不限,不是类的成员也不受他所在的区域访问控制级别的约束。

一般来说,最好在类定义开始或者结束前的位置集中声明友元

友元的声明仅仅指定了访问的权限,而非一个通常意义上的函数的声明。如果我们希望类的用户能够调用某个友元函数,那么我们必须在友元声明之外,再专门对函数进行一次声明。

友元与普通函数的区别在于,友元可以直接访问类的私有成员,而普通函数只能通过类的公有成员访问其私有成员

三、运算符重载

1. 基本概念的碎碎念

对于一个运算符函数来说,它或者是类的成员,或者至少含有一个类类型的参数

我们可以重载大多数(但不是全部)运算符,只能重载已有的运算符,而无权发明新的运算符

当一个重载的运算符是成员函数时,this绑定到左侧运算对象。成员运算符函数的(显式)参数数量比运算对象的数量少一个

2. 调用一个重载的运算符函数

a @ b;
a.operator@(b);
operator@(a,b);

Line1 是隐式调用形式
Line2、3是显式调用形式

2-1. 关于Line2、3

第一种形式是@被重载为类的非静态成员函数的解释方式,这种方式要求运算符@左边的参数必须是一个对象,operator@是该对象的成员函数
第二种形式是@作为类的友元或普通重载函数时的解释方式

2-2. 二元运算符作为类的非静态成员函数、普通函数、类的友元函数重载的区别如下

以非静态成员函数的方式重载二元运算符时,只能够有一个参数,它实际上是函数的第二个参数(即运算符右边的操作数)。其第一个参数(运算符左边的操作数)由c++通过this指针隐式传递,而作为普通函数和类的友元函数重载时需要两个参数。
调用类的重载运算符时,作为类成员函数运算符的左参数必须是一个类对象,而作为友元或普通函数重载的运算符则无此限制。

2-2-1. 重载二元运算符为非静态成员函数的形式如下:
	class X{
		……
		T1 operator@(T2 b){			//实际为T1 operator@(X *this , T2 b)
				……
		}				//其中X *this形参由编译器自动添加
	};

其中,T1是运算符函数的返回类型,T2是参数的类型,原则上T1、T2可以是任何数据类型,而实际上它们常与X相同

2-2-2. 重载二元运算符为类的友元函数或普通函数时需要两个参数,其形式如下:
	class X{
		……
		friend T1 operator@(T2 b,T3 b);			
	};
	T1 operator(T2 a,T3 b){……}	//友元函数定义
	T1 operator(T2 a,T3 b){……}	//普通函数

T1、T2、T3可以是不同的数据类型,但他们通常都是类X。

友元与一般函数重载的区别是:友元可以访问类的任何数据成员,而普通函数只能访问类的public成员

3. 重载运算符类型

(这里不全说了,只说一下Jerry今天委托我讲的几个吧)

3-1. 输入输出运算符

3-1-1. 输入运算符

这里直接给出固定格式

	ostream &operator << (ostream &os , const T1 a)
	{
			os<<……;
			return os
	}

通常,输出运算符应该主要负责打印对象的内容而非控制格式,输出运算符不应该打印换行符

3-1-2. 输入运算符

这里先给出代码

	istream &operator >> (istream &is  , const T1 & a)
	{
		is>>a.xxx……;
		return is;
	}
3-1-3. 需要注意的问题

输入输出运算符必须是非成员函数

输入运算符必须处理输入可能失败的情况(如果输入失败,就将给定的对象默认为空或者其他,这样可以保证对象处于正确的状态),而输出运算符不需要

4. 算数和关系运算符

4-1. 关系运算符

一般来说这个重载后是判断是否相等或者其他关系的,所以返回值是true或false

所以一般用bool型来定义

4-2. 递增和递减运算符

在迭代器类中通常会实现递增运算符( ++ )和递减运算符( – ),这两种运算符使得类可以在元素的序列中前后移动。C++语言并不要求递增和递减运算符必须是类的成员。但是因为他们改变的正好是所操作对象的状态,所以建议将其设定为成员函数

对于内置类型来说,递增和递减运算符具有前置版本也有后置版本,同样我们也应该为类定义两个版本的递增和递减运算符,接下来我们首先介绍前置版本。然后实现后置版本。

4-2-1. 定义前置递增/递减运算符

举例说明

	class  Point{
		public:
			//递增和递减运算符
			Point& operator++();	//前置运算符
			Point& operator--();
	}
	Point& Point :: operator++()
	{
			x++;
			return *this;
	}

为了与内置版本保持一致,前置运算符应该返回递增或递减后对象的引用

4-2-2. 区分前置和后置运算符

由于普通的重载形式无法区分这两种情况。前置版本和后置版本用的是同一个符号,意味着其重载版本所用的名字将是相同的,并且运算对象的数量和类型也相同。

为了解决这一问题,后置版本要接受一个额外的(不被使用)int类型的形参。当我们使用后置运算符时,编译器为这个形参提供一个值为0的实参。

举例说明

	class  Point{
		public:
			//递增和递减运算符
			Point operator++(int);	//后置运算符
			Point operator--(int);
			//其他成员跟之前的版本一致
	}

为了与内置版本保持一致,后置运算符应该返回对象的原值(递增或递减之前的值),返回的形式是一个值而非引用

对于后置版本来说,在递增对象之前需要首先记录对象的状态:

	Point Point :: operator++(int)
	{
			Point ret = *this;
			++*this;
			return ret;
	}

因为我们无需用到int形参,所以勿需为其命名

四、写在最后

看完这篇文章,其实运算符重载的事就学的差不多了,关于+ 、 - 、 * 、 / 的运算符重载,其实是差不多的,在这就没有多家赘述。虽然写的不是很好,但是强烈建议把本篇文章放进收藏夹吃灰


好吧,还是CSDN写文章更香


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jpgxep

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

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

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

打赏作者

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

抵扣说明:

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

余额充值