ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

类和对象3(日期类实现)

类和对象3(日期类实现)

函数内要使用类内的成员变量时不用再写形参类型,直接用就行。

若如下右图写,则是构造函数里声明了局部变量_year/_month/_day,覆盖了类的成员变量,导致成员变量未被初始化。

函数声明与定义分离

.h中函数 类型 函数名(参数列表)

.cpp中函数 类型 头文件中类名::函数名(参数列表)

思考:默认构造需要自己写(初始化),析构函数用默认(无资源释放)。拷贝构造,赋值重载用默认(无资源释放)

首先写构造函数初始化一个日期类,再写一个打印函数

再完成日期的加减比较

设计一个函数要求传入年月后得到对应月份的天数(需判断是否是闰月年及二月天数)

四年一润并且百年不润或者400年一润

该数组常用,设置为静态数组。assert对月份进行限定。该函数常用,设置为类内内联函数。

一、 实现+= + -= -

1.+=

不断在自身上加不断改变自身,所以.h中返回类型是Date &

核心思想:_day+day - 当前月天数=当前天数

用总天数按月扣天数,直至所剩天数小于当前月天数

这里的if(day>0)是传入负数时,+=负数等于-=正数

+ 有两种方法

2. -=

不断在自身上加不断改变自身,所以.h中返回类型是Date &

用当前月天数-要回溯的天数。

若>0,说明回溯后还在本月

若<=0,说明回溯后不在本月,当前月份天数以被减完,借上一月份的天数继续减,直至>0

这里的if(day<0)-=负数等于+=正数

- 有两种方法

二、实现比较大小

先实现比较> ==或 < == 就可以轻松实现其它比较逻辑了

这里实现了< ==

这里将<的情况按先年与年,后月与月,最后日与日都挑选出来了,其他>的情况直接 return false

再实现其他

三、实现前置后置++ --

返回类型依旧是Date&(返回更改后本身) 或Date(传值传参),返回更改后的对象,参数为空

后置时在参数位置写int用来区分前置,int无具体含义不传参

三、日期-日期有意义,算出相差天数

算年月日与年月日之间的差值即相差天数,直接算就行

实际d1 d2谁大谁小我们不知道,设计算法找出d1 d2中大的和小的,让小的不断加至大的,其中加了多少次,就隔了多少天,n始终为正数。实际d1 d2相减结果可能为负数,flag就可以实现对应情况

四、检查月日是否正确

加在构造函数后判断输入日期是否合理

五、若想实现输入任意两个日期,相减即可他们之间相隔天数

需要重载<< >>

<< >>都是是双目运算符,左侧操作数是cout

在库内分别已经将<< 和 >>的运算符重载函数的函数重载(如下图以<< 为例)实现完成,这就是c++可以自动识别要输入输出的内置类型的原因

我们将<< >>重新重载(底层实现时还是用到他们原来的重载)

实现<<

将运算符函数放在日期类Date里面(写成成员函数),这样访问私有成员变量更方便。我们按重载函数中隐藏的this指针指向的是调用的日期类,将cout(是对象)引用传参的准则,设计重载函数。将运算符函数放在日期类Date里面,函数设计如下图void Date::operator<<(ostream& out)。有问题,按原来的输入习惯cout<<d1调用时,隐藏的this与形参out参数不匹配,但如果将调用对象交换,就行,但不理想。

此时将该函数放到.h文件的全局域中再加上日期类d,变成全局函数,即可符合使用习惯。在.cpp中完成该函数,但此时无法方便的使用日期类内的成员函数及变量

需在类内加上友元声明(在类内写friend 函数),在类外声明函数,即可在类外访问私有成员变量

此时仅能单次输入,没有返回out形成链式输入

如何让<<连续输入?

<<和赋值运算符=相似(赋值运算符=是从右往左,返回左操作数),返回值是左操作数,即cout,从左往右,所以将函数类型再改为ostream&,即可

实现>>

其他与实现<<原理一样(内部还是由原来的<< >> 实现,全局函数,需要友元,需要链式实现),因为要往对象内存数据,所以去掉const。

istream与ostream类型对象不支持拷贝构造,不能传值传参,传值返回。只能传引用传参,传引用返回。

将>>加入输入数据是否合法的Check判断,如果一直输入错误就一直提示(while循环,break跳出循环)

>>读取整型,空格 / 换行天然充当分隔符,用来区分年、月、日三个数字。

竞赛有要求时

如下图,d1调用不受const限制的成员函数,相当于要将受const修饰的Date类地址传给不受const修饰的隐藏形参指针变量this,应为this不受const修饰,所以可以通过this修改对象内成员,会将其权限放大,

此时可以改函数内部的私有成员变量,如下图++_year

建议在函数内部不需要修改成员变量的成员函数都加上const

当我们想返回错误指针,空的地址时

以下三图代码一体

对于A aa2=2; 这行代码,发生了隐式类型转换。因为A的构造函数是一个支持单参数的构造函数,所以语法上编译器先用常量2构造一个临时对象,再用临时对象拷贝构造给aa2,相当于构造对象A aa2(2)。编译器实际优化编译时不调用构造临时对象,再调拷贝构造,而是用常量2直接构造对象aa2。

下图,代码st.Push(3)中,用3隐式类型转换构造了一个临时对象A aa2(3)。然后这里再

没有发生类型转换,只是要对临时对象A aa2(3)进行引用传参(重命名),临时对象由于有常性,所以必须加const。由下图压栈时知以后不用先创建对象再将对象传参,而是直接传创建对象时的要初始化的数据,让编译器自动创建对象,这样写起来更简单。注意形参要有const,只有单参数时支持这样写,多参数不支持

当A的构造函数是一个支持多参数的构造函数,与支持单参数的构造函数时相似,只不过多个数据要用{}括起来,

若不想让隐式类型转换发生,在对应构造函数前加关键字explicit即可

返回列表