经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++类中const修饰的成员函数及日期类小练习
来源:jb51  时间:2023/1/30 15:19:56  对本文有异议

一.const修饰类的成员函数

1.问题引出:

给出一段简单的代码

代码段:

  1. #include <iostream>
  2. using std::cin;
  3. using std::cout;
  4. using std::endl;
  5. class Date1
  6. {
  7. public:
  8. Date1(int year = 2000) 类的全缺省构造函数(可无参调用)
  9. {
  10. _year = year;
  11. }
  12. void Prin()
  13. {
  14. cout << "Print Date:" << _year << endl;
  15. }
  16. private:
  17. int _year;
  18. };
  19. int main()
  20. {
  21. const Date1 a; 定义一个const修饰的对象a(该对象只可读,不可被写入)
  22. a.Prin();
  23. return 0;
  24. }

该段程序会编译报错:

2.问题分析

上述代码段出错的原因要从类的成员函数的隐含参数this指针出发进行分析:

注意:

  • 由于a是const修饰的对象,因此&a 取出的是 const Date *类型的指针,该指针只可对a对象的内存空间进行读取操作而不可进行写入操作(该指针的权限为只可读取不可写入)。
  • Prin函数的形参是Date * const this指针,该类型指针同时具有读取和写入内存空间的权限。
  • 将&a赋给Prin的形参this,就会使指针的读写权限被放大,因此编译无法通过(指针是灵活而危险的存在,编译器只允许其读写权限被缩小而不允许其权限被放大)

3.const修饰类的成员函数 

我们知道类的每个成员函数都有一个隐含的this指针形参(类型为:类名*const this)。

为了使被const修饰的对象(比如是上面代码段中的a)可以调用其成员对象,C++规定可以用const来修饰类的成员函数。

类中被const修饰的“成员函数”称为const成员函数,const修饰类成员函数,本质上修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员变量进行修改。(修饰后成员函数的this指针形参类型变为:const 类名* const this)

比如:

const修饰的对象不可以调用非const修饰的成员函数(类指针传参给this指针时读写权限被放大):

非const修饰的对象可以调用const修饰的成员函数(类指针传参给this指针时读写权限被缩小):

const修饰的成员函数内不可以调用其它的非const修饰的成员函数(this指针之间传参时读写权限被放大):

非const修饰的成员函数内可以调用其它的const修饰的成员函数(this指针之间传参时读写权限被缩小):

当类的成员函数中没有对类的成员变量进行任何形式的修改操作时,该成员函数最好都用const来修饰(这样安全同时又使得const修饰的对象可以调用该成员函数)以保证代码的健壮性。

二. 类的两个默认的&运算符重载

编译器会默认生成两个类的&(取地址)重载用于类的取地址操作(如果我们自定义了类的取地址重载则编译器便不会再生成默认的)

C++中,内置运算符若要直接作用于类对象则必须经过重载。

若想取到类对象的地址,我们可以对&运算符进行重载,比如:

  1. #include <iostream>
  2. using std::cin;
  3. using std::cout;
  4. using std::endl;
  5. class Date1
  6. {
  7. public:
  8. Date1(int year = 2000)
  9. {
  10. _year = year;
  11. }
  12. Date1* operator& () 对&进行重载用于非const修饰的对象的取地址
  13. {
  14. return this;
  15. }
  16. const Date1* operator&() const 对&进行重载用于const修饰的对象的取地址
  17. {
  18. return this;
  19. }
  20. private:
  21. int _year;
  22. };
  23. int main()
  24. {
  25. const Date1 a; 定义一个const修饰的对象a(该对象只可读,不可被写入)
  26. Date1 b;
  27. cout << &a << endl;
  28. cout << &b << endl;
  29. return 0;
  30. }

这两个默认成员函数一般不用重新自定义 ,编译器默认会生成,编译其默认生成的&重载和上面我们自定义的成员函数应该没有什么区别(至少功能上没区别)。

三. 日期类小练习 

日期类头文件:

为了提高代码的可维护性和可读性,将日期类的成员函数的声明和定义分开写。

  1. #pragma once
  2. #include <iostream>
  3. using std::cout;
  4. using std::cin;
  5. using std::endl;
  6. //记录日期的类
  7. class Date
  8. {
  9. public:
  10. //Date的构造函数
  11. Date(int day=1, int month=1, int year=1);
  12. //获取月份天数的方法
  13. int GetMonthday(const int month) const;
  14. //类对象的日期打印函数
  15. void Print() const;
  16. //判断某个日期是星期几,并打印出来
  17. void GetWeekDay() const ;
  18. //一组比较运算符的重载
  19. bool operator> (const Date& date)const;
  20. bool operator==(const Date& date)const;
  21. //在逻辑上我们只需定义出大于(或小于)和等于的判断函数,剩余的判断函数我们就可以通过复用的方
  22. 式简化代码书写
  23. bool operator<(const Date& date)const;
  24. bool operator>=(const Date& date)const;
  25. bool operator<=(const Date& date)const;
  26. bool operator!=(const Date& date)const;
  27. //一组日期+(-)整数的操作和+=(-=)整数的操作
  28. Date operator+(const int day)const;
  29. Date& operator+=(const int day);
  30. Date operator-(const int day)const;
  31. Date& operator-=(const int day);
  32. Date& operator=(const Date& date);
  33. //一组前置++(--)和后置++(--)的重载
  34. Date& operator++(); //实现日期类的前置++
  35. Date operator++(int); //实现日期类的后置++
  36. Date& operator--(); //实现日期类的前置--
  37. Date operator--(int); //实现日期类的后置--
  38. //实现时期相减的操作符重载
  39. int operator-(const Date& date)const;
  40. private:
  41. int _day;
  42. int _month;
  43. int _year;
  44. };

日期类的成员函数的实现:

  1. #include "Date.h"
  2. //Date的构造函数
  3. Date ::Date(int day, int month, int year)
  4. {
  5. _day = day;
  6. _month = month;
  7. _year = year;
  8. if (_year <= 0 || _month <= 0 || _month > 12 || _day <= 0 || _day > GetMonthday(_month))
  9. {
  10. cout << "date invalued please exit the app" << endl;
  11. exit(0);
  12. }
  13. }
  14. //获取相应月份天数的方法
  15. int Date::GetMonthday(const int month)const
  16. {
  17. static const int arr[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
  18. int ret = arr[month - 1];
  19. if (((0 == _year % 4 && 0 != _year % 100) || (0 == _year % 400)) && 2 == month)
  20. {
  21. ret++;
  22. }
  23. return ret;
  24. }
  25. //类对象的日期打印函数
  26. void Date::Print()const
  27. {
  28. cout << _year << ' ' << _month << ' ' << _day << ' ' << endl;
  29. }
  30. //判断某个日期是星期几,并打印出来
  31. //注意this指针不能由用户去传
  32. void Date::GetWeekDay()const
  33. {
  34. const char* arr[7] = { "星期一","星期二","星期三","星期四","星期五","星期六","星期日" };
  35. const Date tem(1, 1, 1900);
  36. const int subret = (*this)-tem;
  37. printf("%s\n", arr[(subret % 7)]);
  38. }
  39. //将 > 运算符进行重载
  40. bool Date ::operator> (const Date& date)const
  41. {
  42. if (_year > date._year)
  43. {
  44. return true;
  45. }
  46. else if (_year == date._year && _month > date._month)
  47. {
  48. return true;
  49. }
  50. else if (_year == date._year && _month == date._month && _day > date._day)
  51. {
  52. return true;
  53. }
  54. return false;
  55. }
  56. //将 =运算符进行重载
  57. bool Date:: operator==(const Date& date)const
  58. {
  59. if (date._day == _day && date._month == _month && date._year == _year)
  60. {
  61. return true;
  62. }
  63. return false;
  64. }
  65. //在逻辑上我们只需定义出大于(或小于)和等于的判断函数,剩余的判断函数我们就可以通过复用的方式简化代码书写
  66. bool Date :: operator>= (const Date& date)const
  67. {
  68. if ((*this) > date || (*this) == date)
  69. {
  70. return true;
  71. }
  72. return false;
  73. }
  74. bool Date :: operator < (const Date& date)const
  75. {
  76. if ((*this) >= date)
  77. {
  78. return false;
  79. }
  80. return true;
  81. }
  82. bool Date :: operator<=(const Date& date)const
  83. {
  84. if ((*this) > date)
  85. {
  86. return false;
  87. }
  88. return true;
  89. }
  90. bool Date:: operator!= (const Date& date)const
  91. {
  92. if ((*this) == date)
  93. {
  94. return false;
  95. }
  96. return true;
  97. }
  98. //一组日期+(-)整数的操作和+=(-=)整数的操作
  99. Date& Date::operator+=(const int day)
  100. {
  101. if (day < 0)
  102. {
  103. (*this) -= (-day);
  104. return (*this);
  105. }
  106. _day += day;
  107. while (_day > GetMonthday(_month))
  108. {
  109. if (_month < 12)
  110. {
  111. _day -= GetMonthday(_month);
  112. _month++;
  113. }
  114. else
  115. {
  116. _day -= GetMonthday(_month);
  117. _year++;
  118. _month = 1;
  119. }
  120. }
  121. return (*this);
  122. }
  123. Date Date::operator+(const int day)const
  124. {
  125. Date tem(*this);
  126. tem += day;
  127. return tem;
  128. }
  129. Date& Date::operator-=(const int day)
  130. {
  131. if (day < 0)
  132. {
  133. (*this) += (-day);
  134. return (*this);
  135. }
  136. _day -= day;
  137. while (_day <= 0 )
  138. {
  139. if (_month > 1)
  140. {
  141. _month--;
  142. _day += GetMonthday(_month);
  143. }
  144. else
  145. {
  146. _year--;
  147. _month = 12;
  148. _day += GetMonthday(_month);
  149. }
  150. }
  151. if (_year <= 0)
  152. {
  153. cout << "operation invalued" << endl;
  154. exit(0);
  155. }
  156. return (*this);
  157. }
  158. Date Date::operator-(int day)const
  159. {
  160. Date tem(*this);
  161. tem -= (day);
  162. return tem;
  163. }
  164. Date& Date ::operator=(const Date& date)
  165. {
  166. if (this != &date)
  167. {
  168. _day = date._day;
  169. _month = date._month;
  170. _year = date._year;
  171. }
  172. return (*this);
  173. }
  174. //一组前置++(--)和后置++(--)的重载
  175. Date& Date ::operator++() //实现日期类的前置++
  176. {
  177. (*this) += 1;
  178. return (*this);
  179. }
  180. Date Date ::operator++(int) //实现日期类的后置++
  181. {
  182. Date tem(*this);
  183. (*this) += 1;
  184. return tem;
  185. }
  186. Date& Date:: operator--() //实现日期类的前置--
  187. {
  188. (*this) -= 1;
  189. return (*this);
  190. }
  191. Date Date:: operator--(int) //实现日期类的后置--
  192. {
  193. Date tem(*this);
  194. (*this) -= 1;
  195. return tem;
  196. }
  197. //实现时期相减的操作符重载
  198. int Date::operator-(const Date& date)const
  199. {
  200. int count = 0;
  201. Date min;
  202. if ((*this) < date)
  203. {
  204. min = (*this);
  205. while (min != date)
  206. {
  207. min++;
  208. count++;
  209. }
  210. return -count;
  211. }
  212. else
  213. {
  214. min = date;
  215. while (min != (*this))
  216. {
  217. min++;
  218. count++;
  219. }
  220. return count;
  221. }
  222. }

总结

到此这篇关于C++类中const修饰的成员函数及日期类小练习的文章就介绍到这了,更多相关C++类const修饰的成员函数内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号