<对于数字我们的运算符加减乘除等等都是有意义的,但是如果符号想应用于自定义的数据类型,完成某种意义上的操作呢,就需要运算符重载
加法运算符重载
![](https://img.haomeiwen.com/i16668075/f98eafc1308f2bfe.png)
如上图,对于已有的int,我们使用符号就好了,比如对于Person类,我们定义2个属性,并想通过对象加法完成新对象的属性分别为2者之和。那我们可能就会想到上图的定义一个PersonAddPerson方法,最后返回对象即可,然而我们这么麻烦,其实可以使用编译器已经准备好的函数名 operator+,而我们调用的时候,使用+即可
![](https://img.haomeiwen.com/i16668075/5ad0c2f91e4d9633.png)
如上代码就是个简单的实现,最后不要滥用运算符重载,如加变减这种。
左移运算符重载
我们打印输出使用过cout<<p<<endl;如果p对象有属性,我们想输出p对象的属性值,就可以使用左移运算符的重载
![](https://img.haomeiwen.com/i16668075/28871aa7a8e2b5c2.png)
如上,我们想定义Person的重载,因为不能写在类成员函数,所以只能使用全局函数重载,我们给operator<<传入2个参数,左侧为cout,右侧为Person p的引用,我们cout并不是简单写cout,所以要右键查看定义,可以看到其为ostream类型,我们这里需要使用引用,因为我们不需要创建新的输出流,然后我们内部使用输出流的本身特性接口,就实现了输出属性的操作。当然这只是在cout<<p,我们再想在右侧调用<<就会报错了
![](https://img.haomeiwen.com/i16668075/f8451747fdb7af89.png)
可以看到如上报错,其实这里就涉及到之前的返回自身的对象的思想,我们继续返回输出流本身就好了,就能使用ostream自身的在<<左侧的输出
![](https://img.haomeiwen.com/i16668075/dc809f30be968626.png)
其实这就是cout输出流本身的一种实现返回自身的引用,我们将void 改成ostream &即可,
重载递增运算符
我们想自定义一个整数类MyInteger,然后实现递增++,但是左加和右加必须有区别,我们先实现左加
![](https://img.haomeiwen.com/i16668075/1c845d78a6163f16.png)
如上,我们想输出一个自定义类,我们需要重构<<方法,上节课已经讲过了重载左移,需要全局函数传递,而且使用友元使其能访问到私有属性num。这里左加对应得就是operator++,我们可以考虑返回值或者返回对象,这里我们选择返回自身,这是因为,如果返回int值,则多次递增就变成了int数值的递增,而对象只递增一次,我们需要在++(++mint)这种情况下,mint的num变成2,最终修改完实现。
接下来重载右加,关于右加,你会困惑了,我们好像也就会operator++,但是不传参又会报重复定义错误,其实c++对于右加使用operator++(int)来区别左加,表示是右加。
![](https://img.haomeiwen.com/i16668075/9629cd618c7efdd4.png)
如上,我们这里右加反而不能返回自身,这是因为,我们要实现this.num自加,但是如果先return了,就没有这种操作,只能把临时值存储之前状态,然后返回值,但是mint本身的num也实现自加了
重载赋值运算符
什么时候需要重载赋值运算符呢,我们类对象=某种情况时,需要考虑赋值操作的问题,
![](https://img.haomeiwen.com/i16668075/2926e00967ce8d00.png)
如上,我们定义一个简单的Person类,定义构造方法,然后可以输出属性
![](https://img.haomeiwen.com/i16668075/b8528c8b8aa30713.png)
如果我们把属性开辟到堆区,就把属性变成指针,new int接收地址,然后析构里判断指针不为NULL,就释放,然而我们test函数里使用的是p2,传入p1,使用拷贝方法,这种就引发了异常,当然很明显了你也能知道,这是我们之前讲过了,释放空间时,拷贝为浅拷贝的把属性地址也拷贝了,一个析构释放了空间,另一个还尝试释放相同的空间,就会报错。这时就需要我们使用深拷贝,将赋值操作指针的空间变成新开辟空间
![](https://img.haomeiwen.com/i16668075/ebba938ffcbc153f.png)
如上,我们重载=,需要传入引用Person类型,同时返回的也必须是个引用,因为我们希望能使用连等,这里还需要做个判断,如果当前已经有指向了,需要先清空所占堆区,将指向新开辟空间
其实类初始化时默认就有了4个方法,无参,析构,拷贝和赋值
重载关系运算符
我们都知道基本数据类型的比较啊与或非等等,返回的都是bool型,我们对自定义的类型就需要重载运算符来实现关系比较等等
![](https://img.haomeiwen.com/i16668075/55442ef98e4cab29.png)
没啥说的
重载函数调用操作符
函数调用操作符,其实就是一对小括号
![](https://img.haomeiwen.com/i16668075/9102937d830b750b.png)
如上,我们编写一个类MyPrint类,这样,我们就能使用重载调用操作符,来实现类似函数功能的操作,我们又把这种类似函数的使用叫做仿函数。
![](https://img.haomeiwen.com/i16668075/2ce7530908072017.png)
如上,我们知道匿名对象,我们重载了调用方法的再使用匿名对象就是创建了匿名函数。
当然重载调用有很多种应用,就不一一列举了。
网友评论