运算符重载——基本规则
- 下列的运算符都可以重载,包括()都可以被重新定义行为
运算符重载是说在C++里面可以重载几乎所有的运算符,运算符就是像加减乘除一样的东西。(重载就是可以写函数去改变这些运算符的行为)当这些运算符要对你定义的那个class的object做运算的时候,它可以不使用默认的运算的功能。而使用你所写的那个运算功能来做。
restrictions 限制条件
只能对一个类或者一个枚举的类型重载运算符,不能凭空重载运算符,比如整数的加法是不能重载的,比如 自己定义了类,可以定义一下它们的加法怎么做。
preserve number of operands (重载运算符必须) 保持操作数个数
preserve precedence 保持优先级
type conversion 类型转换
运算符左边那个叫做receiver(决定哪个+)
运算符重载实际上就是把运算符的运算用你写的一个函数去表达出来。所以我们需要为我们要重载的那个运算符写一个特别的函数。那个函数前面要加关键字operatior
运算符重载实际上就是把运算符的运算你写的一个函数去表达出来。所以如上图,需要为你要重载的运算符写一个特别的函数, 就是个普通函数,但前面要用operator这个关键字。上面operator()就是重载乘号*
**这样的运算符可以作为成员函数, 比如
string这个类有一个成员函数叫operator, 做的事plus这个函数。(加法必须有两个算子,其中有个hidden 算子this)所以第三个函数不是成员函数就有两个参数。
最前面那个 const String是返回类型
第三个const说明this 和那个 n都是const。
在函数内返回了一个新的Integer的对象必须是const原因:如果不是const,这个operator plus的返回结果可以做左值,那样就变成了 a + b = 6;
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020082415183349.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2MjY2MjY0,size_16,color_FFFFFF,t_70#pic_center
运算符左边算子那个是receiver,决定了operatior用哪个+,用谁的+来+, 现在因为可以自己定义自己的+所有可能有不同的+, 可能有Integer的+, 可能有float, string的+等等。发现左边的receiver是个Integer的对象, 这个+就用Integer里面那个成员plus来做+。
x.operator+(y)
operator+ 就是函数名
receiver是整数决定了operatior用整数,那么y就必须是整数。y就必须提供一种方法把自己变成整数。y提供不了,所以编译错误。
- z = x + y(√) 用的overloaded的plus,
- z = x + 3(√) 这两个类型虽然不一样, 一个Integer,一个Int,receiver是x, 所以Integer的那个overloaded plus会被调用,3不能直接用, 又因为上上张图Integer的构造函数,拿一个整数可以做出Integer来, 所以实际发生的事情就是会用那个构造函数把3构造成一个Integer的对象,(匿名的, 因为无变量)
- z = 3 + x(×) receiver是int, 所以直接用整数加减法,但是后面的Integer又没有手段把自己变成int
如上图一元运算符不需要有任何参数,如果不给参数就表示对自己取负,(不是对自己取负,而是对自己的值取负以后制造一个新的值来)
如上图:如果不作为成员函数,作为全局函数,需要把两个算子都写上去。
如上图 全局函数z = 3 + y 是可以的。(因为这个时候compiler发现说对于3用整数加法是没法做的, 但如果把3变成一个Integer是可以做的, 于是就会用那个)
做运算符重载时选择成员函数还是非成员函数?如下图
- 单目运算符应该做成成员的,第二个点是必须做成成员
- 二元运算符必须做成非成员的。
运算符重载——原型
- 常见原型
为了便于区分:++在前面的没有任何参数,++在后面的括号里有type
++在前面返回reference, ++在后面返回的是一个Integer对象,为什么?
- ++a返回的是a加了以后的结果, 也就是a当时的结果, 所以直接返回a的reference,前面的const是禁止你拿它做左值。(++a做左值, ++a = 6, it is error)(也可以返回不带&的, 不过带了&更节约)
- a++意味着返回加以前的结果, a++做完以后a已经不是a++以前的那个结果了, 返回reference是无用的,那个reference是不存在的
index是[]的的意思
运算符重载——赋值
- 第一行叫做拷贝构造,第二行叫做赋值。拷贝构造的时候做了一个新的对象出来, 赋值的时候是把另外一个对象的值赋给了已有的对象。
- 第一行调用拷贝构造函数,第二行(赋值是一个运算符, 如果你重载了这个运算符,它就会调用你的那个运算符,不然会用系统默认的)
运算符重载——类型转化
One的构造函数能把one变成一个two,所以最后一行代码没错。
如下图:如果不希望编译器自动把one 给你变成 two,加一个keyword explicit
另外一个方法是如下图做一个专用的类型转换函数
operator double()const的意思是要用这个函数把这个class的对象,this转换成double(最后const的意思是:做的是转化,把this转换掉了,this并没有改, 只是做了个新的东西出来)
通常格式就是 上图这样。