作者:几冬雪来
时间:2023年5月8日
内容:C++类和对象内容讲解
目录
前言:
1.操作符重载(续):
前置++和后置++:
日期减日期:
<<操作符:
结尾:
前言:
在上一篇博客中,我们借助了日期类的代码实现了赋值重载等操作,今天我们就对其进行进一步的讲解。
1.操作符重载(续):
在上一篇博客中我们大致的讲解了操作符重载,并且书写了日期类的日期加天数的代码。而接下来我们就来实现日期类代码的其他形式。
在我们的日期类代码中,乘和除基本没有意义。
并且日期加日期也没有意义。
而我们的日期减天数和日期减日期就有意义,接下来我们就来写日期减天数的代码。
这里我们就可以先写出-=的代码,再对其进行附用来书写出我们日期减天数的代码。
在这里我们也可以成功的实现日期减天数的代码。
但是实际上在我们的日期类中还有许多离谱的操作。
就类似我们的上面的这段代码,我们实现的是一个日期减天数的操作。
如果在这里我们这里减等于的日期是一个负的天数会怎么样?
这里我们的日期减等于一个负的天数,在我们看来就是加上这个天数。
因此在这里我们就需要对减等于处的代码进行修改。
说是修改其实也就是追加一个设定。
在减等于处的开头进行判断,如果在这里我们的day小于0的话。
这个时候我们就要去附用加等于的操作了,并且在附用之前我们需要将day的符号由负号转正。
同样的情况,在加等于处如果加等于一个负数的话,在这里就要附用减等于的代码。
前置++和后置++:
接下来我们就来延续上一篇博客最后讲解到的++操作。
在编译器中我们分为前置++和后置++。
而这里,如果是内置类型的前置++和后置++并没有对我们的代码有什么过大的影响。
但是在自定义类型中我们就需要去注意前置++和后置++所带来的不同。
如果是我们需要一个值来接收我们返回值的话。
在底层处它们的写法也会发生一定的变化。
但是,这里有一个要科普的知识点。
因为分辨前置和后置++,在内置类型影响较小,在自定义类型影响较大。
我们在声明的时候不能用同一个函数对其声明。
在有些语言中,因为过于麻烦的原因它们可能会将++操作符pass掉,只留下+=操作符。
日期减日期:
接下来我们就来书写日期减日期的代码。
日期减日期,最后减出来的是两个日期的天数差。
但是在这里,日期减日期的代码并不是那么好写的。
因为平年和闰年二月份的差异,我们的代码不能直接进行相减。
因此我们不采取这种方式,而是对前面的代码进行附用的操作。
这里我们采取的另一种方法就要用小的日期加至大的日期。
这里就是两个日期中相差的天数。
这里要注意的是,在开始的时候我们因为是需要小日期加到大日期,所以我们要先进行判断。
判断是否要对其进行交换的操作。
接下来就是两个日期间进行比较,并且定义一个n来表示相差的天数,在最后我们返回的日期天数还要乘我们的flag。
因为在这里,我们小日期减大日期减出来的是一个负数。
虽然在代码中我们使用的是大日期减去小日期,然后再让小日期加到大日期。
但是实际上,外面并没有进行交换的操作,我们的小日期减去大日期是负数,因此在最后我们要乘以flag,将其进行改变。
从我们上面的结果来看我们也是成功的实现了操作。
<<操作符:
在这里我们实现了上面的一系列的操作。
但是在这里如果要打印出我们的结果的话,是这个样子调用的。
那么这个地方我们能不能实现,打印结果的分开声明和定义。
那当然是可以的。
像我们的代码要从左边的形式装换为右边这种形式。
这样做可以一定程度的增强代码的可读性。
在这里要实现这种转换的话,我们要在头文件中先进行声明。
但是右边写法的声明相比较与我们前面那些代码的声明方式略有不同。
在这里我们的声明和定义要写成这种形式。
这里涉及我们一部分类和对象后面板块的知识,现在我们就先看一下。
但是这样写的话,我们就能成功的打印出我们的结果吗?
并没有,这里会发生报错。
这是因为:
而要解决这个问题也是十分的方便。
就是在一开始的地方将我们的d6和cout互换位置。
交换了之后就可以顺利的打印出我们的结果。
可这样写虽然代码也可以跑起来,却不符合我们的书写习惯。
因为在C++中我们通常都默认cout是写在最右边处的。
并且在这里我们也不可能通过修改使其变成cout写在最左边的形式,这是库里面所规定的。
这里要让cout在左边有两种书写方式。
这里的第一种方法就是写在我们的公有区域。
但是众所周知,如果写在公有区域要去调用类中的内容就要注意私有和维护的问题。
解决它的方法也是有的。
这里就是在我们的类中进行GetYear,GetMonth等操作,最后再写到我们的定义中去,这里就可以通过这种方式解决。
而第二种方法则是友元函数。
使用友元函数声明也可以解决我们这个问题。
友元函数等我们以后再来讲解。
那么这里还有一个问题,类似我们下面的这种多段流插入的代码。
因为是多段的流插入,使用在这里就应该要有我们的返回值。
我们的代码就要进行修改。
当然在这里既然有我们的流操作的操作符,那么肯定要有我们的流提取的操作符。
而我们的流提取的操作符则可以通过我们流操作的代码修改而来。
这里要注意的是,我们的流插入中d的内容不用修改,所以我们加入const。
但是在流提取中我们两个参数都不能用const固定,它们都是要改变的。
在书写完了上面的这一系列的代码,接下来我们就来慢慢的解决一些小问题。
像上面我们在流插入处输入一个不合理的日期,但是我们的编译器还是将其打印出来了。
因此我们还要对其进行一个判断的操作。
既然在流插入会出现这个问题,那么在流提取处我们也要对其进行判断。
注意在这里我们的GetMonthDay要改为静态的。
接下来讲解我们的最后的一个问题。
比如在我们打印的时候。
在打印的时候我们去调用了类中的Print,但是从结果上来看我们的第一个日期可以进行调用打印,但是我们的第二个日期却不能。
这里的这个问题就要回到我们以前的有关权限的问题。
接下来我们就来分析一下。
在这里传递的时候就会出现问题。
第一个代码我们传递的内容是Data*,但是第二段代码不是Data*而是const Data*,在接收的地方为Data*。
这样子就导致了我们的第一个代码为权限的平移,编译器是允许的,但是第二段代码则是权限的放大,代码会报错。那么我们如何去解决这个问题?
这里的解决方法十分的简单,就是在接收处将我们的Data* this修改为const Data* this。
在这里我们的第一段代码就会变为权限的缩小,而且第二段代码会变为权限的平移。
而在编译器中权限的缩小和平移的操作都是被允许的。
那么怎么对其进行修改就是一个问题,因为在代码中我们的this指针是隐含的不能显示着写,我们无法直接对其进行修改,那么该在哪里加入我们的const呢?
这个地方我们只能将const加在我们代码的后面,用来修饰我们的*this。
这也是没有办法只能这样写。
普通函数后面加上const以后,普通和const对象都可以调用。
但是并不是所有成员函数都要加const,要修改的对象成员变量的函数不能加入const。
这里我们就可以得出一个结论:
只要成员函数内部不修改成员变量,例如:比较大小,+等不用改变自身就应该加上const,这样const对象和普通对象都可以调用。类似:+=,-=等操作符要改变自身的就不能加上const。
结尾:
到这里我们类和对象(中)的知识就要学习完毕了,再过不就我们的类和对象的内容就要完结了,完结了类和对象后,我们的C++的第一个大板块就要结束了。这几篇C++的难度相比之前有所提高,我们要多去消化它。最后希望这篇博客能给大家带来帮助。