今天,继续和大家分享与类和对象相关的知识,本次内容会涉及赋值运算的重载,日期类的实现以及const成员等方面。

赋值运算符的重载

对于内置类型,我们可以使用赋值符号直接对进行拷贝一份

C++-类和对象(4)_赋值

从图中我们能看到变量j对变量i的数据进行拷贝。图中的代码增加了注释,但即使没有注释,我们也能明白这是拷贝。

C++为了增加代码的可读性,引入了运算符重载。

运算符重载是具有特殊函数名的函数,它也具有返回值及参数列表。我们以日期类的赋值运算为例实现一个函数:

C++-类和对象(4)_数据_02

首先,我们可以知道内置类型的赋值符号可以实现连等

C++-类和对象(4)_运算符_03

这说明,内置类型重载的赋值符号函数的返回值是赋值的数据。因此,我们实现的赋值运算符函数,也应该以赋值的数据作为返回值。我们的日期类赋值运算符重载函数结束时,对象并没有被销毁,因此,我们可以加上引用,进行引用返回,避免了传值返回的拷贝开销。

返回值确定后,我们需要使用operator这个关键字加上相应的运算符作为函数名,然后,加上相应的形参,一个运算符重载函数就完成了。

我们对赋值运算符来进行总结一下:

1.赋值运算符的格式

·参数类型 const &T ,传递引用,提高传参效率

·返回值 T& 引用返回,提高返回效率,返回值的目的为了支持连续赋 值

·检测是否是自己给自己赋值

·返回*this 要复合连续赋值的含义

2.赋值重载只能重载成类的成员函数,不能重载成全局函数。

3.若用户显示生成,编译器会默认自动生成一个赋值运算符重载函数。而编译器生成的赋值运算符重载函数,只会进行字节序的拷贝,也就是浅拷贝,如果成员变量无动态申请空间资源便可以不写。像栈和队列这些就需要自己写。

对于运算符的重载这方面还有一些需要注意的点:

1.operator不能连接其他符号创造新的操作符,比如operator@。

2.重载操作符必须有一个类类型参数(这个参数包括this指针),当我们定义在类里就已经满足条件了,如果定义在类外,则需要在参数列表中加一个类类型,避免和内置类型的运算符冲突。

3.内置类型的运算符,其含义不能更改。比如int的前置++,自身加一,不能改成自身减一

4.

”.*“,"sizeof","?:","::",".",

以上这五个运算符不能重载

对于运算符这一块的内容,并不复杂,主要是运用。

接下来,我们来运用一下,简单的实现一个日期类:

日期类的实现

前面,我们已经实现了构造函数,拷贝构造函数以及赋值运算符重载这三个函数。

C++-类和对象(4)_运算符_04

现在,我们接着把它完善。

某一个运算符要不要重载,是根据它有没有意义的来确定的。而日期类的加上天数或减去天数,得到未来或过去某一天的日期,这是有意义的,那我们就先从加号和减号运算符这着手。

日期类加号的重载

C++-类和对象(4)_运算符_05

在实现加法运算符重载前,我们先使用内置类型的加号的效果,从图中我们不难发现,加号的使用后会返回相加的结果,但不会改变变量自身的数据。

好了,有了对加号的基本认识后,我们来实现一个日期类的加号。对于天数的加减会涉及到月份的天数获取,我们先写一个获取相应月份的天数的函数。

当我们知道年月后才可以判断一个月有多少天,因此,函数需要年月两个参数。每个月有多少天,我们可以放到一个数组中存放。我们把数组下标为0的位置存放0,这样相应的月份就能对应上相应的天数了。获取天数这个函数,我们会平凡的使用,所以,数组可放到静态区,不用每次调用都创建一遍。闰年的二月份会多出来一天,这里我们需要加一个判断。

思路我们理清了,来看看代码的实现:

C++-类和对象(4)_运算符_06

获取天数的功能有了,我们接着往下,根据运算符重载的格式,给出返回值,函数名,形参列表。紧接着是实现,首先,我们不能修改本身的数据,需要拷贝一份。拷贝完后,我们对拷贝的数据进行操作,先把传过来的天数加上。然后,判断天数是否合规(也就是大不大于现在月份该有的天数),若有违规,就进行修改。月份的不断修改,也可能出现不正常数据,这里也需要加上判断。

思路理清了,我们来看看代码的实现:

C++-类和对象(4)_赋值_07

日期类减号的重载

加号的重载完成了,我们来分析一下减号:

C++-类和对象(4)_运算符_08

从图中,我们可以看到,减号的原则和加号基本是一致的,会返回两数相减的结果但不会修改本身的数据。

同样,我们根据运算符的重载格式,给出返回值,函数名和参数列表。由于原数据不能修改,我们需要拷贝一份。拷贝完后,对拷贝的数据进行操作,减去传参传过来的天数,然后,对天数进行判断是否合规。若不符合现实的规定,则进行相应的修改。月数的不断变化,也会出现不符合现实的数据,这里也需加上判断。

思路理顺了,我们来看看代码的实现:

C++-类和对象(4)_数据_09

我们来简单的测试一下,这两个代码:

C++-类和对象(4)_数据_10

C++-类和对象(4)_赋值_11

通过图片的结果看,函数的功能没什么问题。难道真的没有问题了吗?我们再看看下面这组测试用例:

C++-类和对象(4)_赋值_12

C++-类和对象(4)_数据_13

当我们在天数前面加上负号后,两个函数的功能都出现了问题,但网页计算器却还能准确的计算出结果。那这个问题怎么解决呢?负负得正,加负数相当于减,我们只需要加上一个判断,若为负数,互相对调就行了。

我们来看看改进的代码:

C++-类和对象(4)_运算符_14

我们在来看看测试结果:

C++-类和对象(4)_赋值_15

C++-类和对象(4)_赋值_16

改进后,结果便被准确算出了。

接下来,我们来实现前置++和后置++

日期类前置++和后置++的实现

前置++和后置++的功能,相信大家都不陌生。我们来看一下它们的使用:

C++-类和对象(4)_运算符_17

从程序结果来看,我们不难发现不论是前置++还是后置++都会对自身数据进行加一的操作。那它们是如何实现自身修改的同时前置++输入11,后置++输出10的呢?

你可别忘了还有函数的返回值呀!前置++返回修改后的数据,后置++返回修改前的值。这样就实现了不同的功能,既可以先++,在使用数据,也可以先使用数据,再++。

理清了功能实现方法,我们来看看代码的实现:

C++-类和对象(4)_运算符_18

前置++和后置++都是进行加一,我们可以复用之前的加号重载函数,实现。前置++的数据在函数结束后,并不会销毁,可以使用引用返回。后置++,出了函数数据会销毁,需要使用传值返回。 后置++和前置++的运算符都是++,为了能让后置++和前置++正确的构成重载。C++规定:后置++多参加一个int类型的参数,加以区分。但调用函数时并不需要进行传递,编译器会自动传递。

接下来,我们来看一下,运行的结果。

C++-类和对象(4)_运算符_19

从结果看,我们的程序是没问题的。

好了,到这里,我们本次的分享就到此结束了,不知道我有没有说明白,给予你一点点收获。如果你有所收获,别忘了给我点个赞,这是对我最好的回馈,当然你也可以在评论发表一下你的收获和心得,亦或者指出我的不足之处。如果喜欢我的分享,别忘了给我点关注噢。