【C++初阶】类和对象修炼下 我不是女神ヾ 2024-04-03 12:19 35阅读 0赞 #### 文章目录 #### * 一.四大默认成员函数 * 二.获取某年某月的天数 * 三.日期+=天数和日期+天数 * 四.日期-=天数和日期-天数 * 五.日期比较 * 六.日期++和++日期 * 七.日期-日期 > 类和对象下呐主要是给大家讲一下日期类的实现,至于为什么不实现一个栈呐,那是因为目前学到的拷贝构造和赋值重载都是属于一种浅拷贝,而对于栈类我们需要使用深拷贝. ## 一.四大默认成员函数 ## 这里就不过多赘述了 class Date { public: //全缺省的构造函数 Date(int year = 2022, int month = 10, int day = 13) { _year = year; _month = month; _day = day; if (!(_year > 0 && _month >= 1 && _month <= 12 && _day >= 1 && _day <= GetMonthDay(_year, _month))) { cout << "输入的日期不合法" << endl; Print(); } } //拷贝构造(其实对于日期类可以不用写拷贝构造) Date(Date& d) { _year = d._year; _month = d._month; _day = d._day; } //赋值重载(其实对于日期类可以不用写拷贝构造) Date& operator=(const Date& d2) { _year = d2._year; _month = d2._month; _day = d2._day; return *this; } //析构函数:(其实对于日期类可以不用写析构函数) ~Date() { _year = _month = _day = 0; } //打印日期 void Print() { cout << _year << "-" << _month << "-" << _day << endl; } private: // 内置类型 int _year; int _month; int _day; }; > 注意:下面所写的函数都是日期类中的成员函数,这就意味着第一个参数都是隐含的this指针. ## 二.获取某年某月的天数 ## > 年分为闰年和平年,月也分为1-12月,所以对于任意一年的12个月中每一个月的天数都是基本一样的,维度在2月因为平年还是闰年相差一天.所以如果你要获取某年某月的天数,就只需对于在2月,且是闰年特殊+1天就可以. //获取某年某月的天数 int GetMonthDay(int year, int month) { int monthDay[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; int day = monthDay[month]; if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0 && month == 2) { ++day; } return day; } 这里值得一提的是,这里有两个可以优化的地方: 1. 这里的GetMonthDay()函数会被反复调用,且monthDay数组始终不变,所以建议定义成static静态的 2. 这里的if判断条件中,除法和取余的运算符效率低,所以建议把month==2的条件写在最前面 也就是这样: //获取某年某月的天数 int GetMonthDay(int year, int month) { int _month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; int _day = _month[month]; if (month == 2 && year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { ++_day; } return _day; } ## 三.日期+=天数和日期+天数 ## 这里可以通过举例内置类型中+=和+运算符的使用特点 比如: c=a+=b和c=a+b这个例子 \+=和+有一定的相似点: > 返回值和参数在类型和个数上都是一样的 > > 返回值:Date& > > 参数1:隐含的this指针 > > 参数2:要+的天数 但是,+=和+也有不同点: > c=a+=b这里a的值在运算前后发生改变, > > c=a+b这里a的值在运算前后没有改变. > > 这里日期1+=天数和日期1+天数两个函数的区别在于: > > * 日期1+=天数中,日期1在运算前后发生改变, > * 日期1+天数中,日期1在运算前后没有改变. 这里先给大家实现operator+=(int day)函数: ![image-20221013235137481][] ps:值得注意的是12到1月的转变的时候,年份也要变 Date& operator+=(int day) { if (day < 0) { return *this -= -day; } _day += day; while (_day > GetMonthDay(_year, _month)) { _day -= GetMonthDay(_year, _month); ++_month; if (_month == 13) { _month = 1; ++_year; } } return *this; } ![6a8c671bdc44ec81aaceb4a6ba47ce51.png][] 然后我们来实现一下,operator+(int day)函数: > 这里我们可以调用拷贝构造一个替身,让替身的this发生改变,然后返回替身,那么就可以得到返回值的同时,本体的this却没有发生改变. //日期+天数 Date operator+(int day) { Date ret(*this); if (day < 0) { ret -= -day; return ret; } ret += day; return ret; } ## 四.日期-=天数和日期-天数 ## 这里和三的区别和相同点一样,这里不过多赘述. 这里是日期-天数,那么同样的先全部减在天数上,然后借位,值得注意的是12到1月的转变的时候,年份也要变 ![image-20221014001030087][] 日期-=天数: //日期-=天数 Date& operator-=(int day) { if (day < 0) { *this += -day; } _day -= day; while (_day <= 0) { --_month; if (_month == 0) { _month = 12; --_year; } _day += GetMonthDay(_year, _month); } return *this; } 日期-天数: //日期-天数 Date operator-(int day) { Date ret(*this); if (day < 0) { ret += -day; return ret; } ret -= day; return ret; } > ps:这里传入的天数一般都是正数,如果天数是负数的话,日原来的日期-天数就想当与日期+(-天数),同样可以代码复用. ## 五.日期比较 ## 这里代码书写起来比较简单,这里只想给大家讲一下复用的问题:写了>和==其他日期比较,比如>=或者<或者!=都可以通过函数复用实现. //==运算符 bool operator==(const Date& d) { return _year == d._year && _month == d._month && _day == d._day; } //<运算符重载 bool operator<(const Date& d) { return !(*this > d || *this == d); } 复用>和==的代码,可以完成: //>=运算符 bool operator>=(const Date& d) { return *this > d || *this == d; } //<=运算符 bool operator<=(const Date& d) { return !(*this > d); } //!=运算符 bool operator!=(const Date& d) { return !(*this == d); } ## 六.日期++和++日期 ## 首先,日期++和++日期也就是我们常说的b=a++和b=++a的区别: 但是这里会出现一个比较尴尬的问题: > 这里的要写的两个运算符重载函数都使用的是一个运算符++,所以在书写成员函数的时候函数名肯定都是 > > operator++,那么当我们写同时使用了d2=d1++和d2=++d1的时候,我们就写一个函数肯定不行,所以C++语法就规定: > > **前置++和后置++的运算符重载函数使用operator++作为函数名,但是前置++的运算符重载函数不带参数,后置++的运算符重载函数带一个int类型作以区分.** //前置++: 比如y=++x; Date& operator++() { *this += 1; return *this; } //后置++: 比如y=x++; Date operator++(int) { //记录最初值 Date ret(*this); *this += 1; //返回最初值 return ret; } > 值得注意的是,后置++中只能传值返回,因为出了作用域ret就不存在了,不能传引用返回. > > 所以后置++这里要调用两次拷贝构造,一般推荐使用前置++ ## 七.日期-日期 ## 日期+日期就和指针+指针一样,没有任何意义,所以这里不讨论日期+日期 另外运算的结果是两个日期相差的天数,所以没法日期-=日期 所以我们只讨论日期-日期: 方法1:从日期1遍历到日期2计数,直至相等,推荐 //日期-日期: int operator-(const Date& d) { Date max = *this; Date min = d; int flag = 1; if (*this < d) { max = d; min = *this; flag = -1; } int count = 0; while (min != max) { ++min; ++count; } return flag * count; } 方法2:选定一个起始位置0-1-1,分别计算日期1和日期2到起始位置的天数,然后两个天数相减 注意:这里要先求从0到\_year-1这几年的整年天数,再算当前年从1- \_month-1这几月的天数,最后再加上 \_day //日期-日期: int GetDay(const Date& d) { int day = 0; for (int i = 0; i < d._year; i++) { day += 365; if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) { ++day; } } for (int i = 1; i < d._month; i++) { day += GetMonthDay(d._year, i); } day += d._year; return day; } int operator-(const Date& d) { int day1 = GetDay(*this); int day2 = GetDay(d); return day1 - day2; } ![image-20221014010558939][] ![image-20221014011430354][] [image-20221013235137481]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/03/0aecf290deb24a3b8f93728b5e0d2df0.png [6a8c671bdc44ec81aaceb4a6ba47ce51.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/03/e9eb4bf29e724f078e75de96f192446a.png [image-20221014001030087]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/03/39cf537bdcfa4b0485cff9986e533d71.png [image-20221014010558939]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/03/3a29860f10fe473bb821a4c1715c9cab.png [image-20221014011430354]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/03/52b8a2635db8444ba4027d3bb8b007f8.png
相关 【C++初阶】类和对象修炼下 文章目录 一.四大默认成员函数 二.获取某年某月的天数 三.日期+=天数和日期+天数 四.日期-=天数和日期-天数 五.日期比较 六. 我不是女神ヾ/ 2024年04月03日 12:19/ 0 赞/ 36 阅读
相关 【C++初阶】类和对象修炼中 文章目录 一.构造函数 1.构造函数的简单认识 2.内置类型和自定义类型的处理方式 3.日期类和资源清理类 二.析构函 ゝ一纸荒年。/ 2024年04月03日 12:17/ 0 赞/ 33 阅读
相关 【C++初阶】类和对象修炼上 > 这一专题<类和对象>是C++学习者的第一道小坎,我将分为上中下三节给大家讲解 > > 1. 类和对象上:类和对象的引入,包括一些细碎的知识点,包括面向对象思想,类的实例 爱被打了一巴掌/ 2024年04月03日 11:33/ 0 赞/ 32 阅读
相关 【C++初阶】:类与对象(上) 类与对象 一.面向对象的初步认识 二.初步认识类 三.类的权限 四.类的声明和定义 五.封装 六.类的实例化 七.类的大小 柔情只为你懂/ 2024年03月23日 15:54/ 0 赞/ 7 阅读
相关 【C++初阶】:类与对象(下) 类与对象 一.再谈构造函数 1.初始化列表(构造函数的一部分) 2.explicit关键字 二.static成员 三.友元 爱被打了一巴掌/ 2024年03月22日 14:37/ 0 赞/ 7 阅读
相关 【C++初阶】:string类 string 一string的基本用法 二.迭代器 1.基本使用 2.语法糖 3.反向迭代器 4.con 缺乏、安全感/ 2024年03月17日 09:59/ 0 赞/ 13 阅读
相关 【C++】类和对象(下) 文章目录 一、再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit关键字 二、stati 梦里梦外;/ 2023年10月14日 22:51/ 0 赞/ 91 阅读
相关 【C++ 初阶】类和对象 目录 一、面向过程vs面向对象 二、类的限定符及封装 三、类的实例化 四、this指针 五、默认成员函数 1. 构造函数 梦里梦外;/ 2022年09月16日 11:18/ 0 赞/ 153 阅读
还没有评论,来说两句吧...