• C++——类和对象3|日期类型|Cout运算符重载|Cin运算符重载|const成员|


    目录

    日期类型 

    Date.h 

    Date.cpp 

    Test.cpp 

    实现Cout运算符重载 

    实现Cin运算符重载 

    根据日期算星期 

    修改后完整代码  

    Date.h 

    Date.cpp 

    const成员

     取地址及const取地址操作符重载

    习题  计算日期到天数转换 



    日期类型 

    Date.h 

    1. #include
    2. using namespace std;
    3. class Date
    4. {
    5. public:
    6. // 获取某年某月的天数
    7. int GetMonthDay(int year, int month)
    8. {
    9. static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    10. int day = days[month];
    11. if (month == 2
    12. && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
    13. {
    14. day += 1;
    15. }
    16. return day;
    17. }
    18. Date(int year = 1900, int month = 1, int day = 1)
    19. {
    20. _year = year;
    21. _month = month;
    22. _day = day;
    23. }
    24. void Print();
    25. bool operator==(const Date& d);
    26. bool operator!=(const Date& d);
    27. bool operator>(const Date& d);
    28. bool operator<(const Date& d);
    29. bool operator>=(const Date& d);
    30. bool operator<=(const Date& d);
    31. Date operator+(int day);
    32. Date& operator++();//默认是前置++,返回+完后的值,用引用返回
    33. Date operator++(int i);//后前置++,里面要写一个参数,这里的参数可以不用形参接收,括号里直接写int就行,但加了参数也无所谓,这里的参数只是为了区分
    34. //C++为了区分前后置++,使用重载进行区分,后置++重载增加一个int参数跟前置构成函数重载进行区分
    35. Date& operator+=(int day);
    36. Date operator-(int day);
    37. Date& operator-= (int day);
    38. Date& operator--();
    39. Date operator--(int);
    40. int operator-(const Date& d);
    41. private:
    42. int _year;
    43. int _month;
    44. int _day;
    45. };

    Date.cpp 

    1. #include"date.h"
    2. bool Date::operator==(const Date& d)
    3. {
    4. return _year == d._year &&
    5. _month == d._month &&
    6. _day == d._day;
    7. }
    8. bool Date::operator!=(const Date& d)
    9. {
    10. return !(*this == d);
    11. }
    12. bool Date::operator>(const Date& d)
    13. {
    14. if (_year > d._year)
    15. return true;
    16. else if (_year == d._year && _month > d._month)
    17. {
    18. return true;
    19. }
    20. else if (_year == d._year && _month == d._month && _day > d._day)
    21. {
    22. return true;
    23. }
    24. else
    25. return false;
    26. }
    27. bool Date::operator<(const Date& d)
    28. {
    29. return !(*this >= d);
    30. }
    31. bool Date::operator>=(const Date& d)
    32. {
    33. return (*this > d) || (*this == d);
    34. }
    35. bool Date::operator<=(const Date& d)
    36. {
    37. return !(*this > d);
    38. }
    39. // 自身要改变
    40. Date& Date::operator+=(int day)
    41. {
    42. _day += day;
    43. while (_day > GetMonthDay(_year, _month))
    44. {
    45. _day -= GetMonthDay(_year, _month);
    46. _month++;
    47. if (_month == 13)
    48. {
    49. _month = 1;
    50. _year ++;
    51. }
    52. }
    53. return *this;
    54. }
    55. //自身不改变
    56. Date Date::operator+(int day)
    57. {
    58. Date ret(*this);//拷贝构造
    59. //Date ret= *this;在这里,这条语句是拷贝构造,拿*this初始化ret,已经存在的对线才是赋值
    60. ret += day;
    61. return ret;//传值返回的时候,会生成一份拷贝
    62. }
    63. void Date::Print()
    64. {
    65. cout << _year<<"/" << _month<<"/"<<_day << endl;
    66. }
    67. Date& Date::operator++()//前置
    68. {
    69. *this += 1;
    70. return *this;
    71. }
    72. Date Date::operator++(int)//后置,返回++之前的值
    73. {
    74. Date tmp(*this);
    75. *this += 1;
    76. return tmp;
    77. }
    78. Date& Date::operator-= (int day)
    79. {
    80. _day -= day;
    81. while (_day <= 0)
    82. {
    83. --_month;
    84. if (_month == 0)
    85. {
    86. --_year;
    87. _month = 12;
    88. }
    89. _day += GetMonthDay(_year,_month);
    90. }
    91. return *this;
    92. }
    93. Date Date::operator-(int day)
    94. {
    95. Date ret = *this;
    96. ret -= day;
    97. return ret;
    98. }
    99. Date& Date::operator--()//前置--
    100. {
    101. *this -= 1;
    102. return *this;
    103. }
    104. Date Date::operator--(int)//后置--
    105. {
    106. Date tmp = *this;
    107. *this -= 1;
    108. return tmp;
    109. }
    110. int Date::operator-(const Date& d)//日期相减
    111. {
    112. int flag = 1;
    113. Date max = *this;
    114. Date min = d;
    115. if (*this < d)
    116. {
    117. min = *this;
    118. max = d;
    119. flag = -1;
    120. }
    121. int n = 0;
    122. while (min != max)
    123. {
    124. ++min;
    125. ++n;
    126. }
    127. return n*flag;
    128. }

    Test.cpp 

    1. int main()
    2. {
    3. Date d1(2001, 1, 3);
    4. Date d2(2023, 7, 23);
    5. Date d3(2022, 6, 23);
    6. cout << (d1 < d2) << endl;
    7. cout << (d1 > d2) << endl;
    8. cout << (d1 == d2) << endl;
    9. cout << (d1 < d3) << endl;
    10. cout << (d1 > d3) << endl;
    11. cout << (d1 == d3) << endl;
    12. Date ret1 = d1 + 100;
    13. ret1.Print();
    14. Date ret2=++d1;//转换为d1.operator++(&d1)
    15. ret2.Print();
    16. Date ret3=d2++;//转换为d1.operator++(&d2,0)
    17. ret3.Print();
    18. d1 += 100;
    19. d1.Print();
    20. d1 -= 100;
    21. d1.Print();
    22. Date ret4 = d1 - 1000;
    23. ret4.Print();
    24. int ret5 = d1 - d2;
    25. cout << ret5 << endl;
    26. return 0;
    27. }

     

     一个类到底可以重载哪些运算符,要看哪些运算符对这个类型有意义

    日期减天数思路:先给天减,如果不够(<=0)就借位

    程序有缺陷,构造这里出现了问题

    我们在类里面加上判断日期的函数即可或者用assert去判

    1. Date(int year = 1900, int month = 1, int day = 1)
    2. {
    3. _year = year;
    4. _month = month;
    5. _day = day;
    6. //assert(CheckDate());
    7. if (!CheckDate())
    8. {
    9. Print();
    10. cout << "日期非法" << endl;
    11. }
    12. }
    13. bool CheckDate()
    14. {
    15. if (_year >= 1 && _month < 13 && _month>0 && _day > 0 && _day <= GetMonthDay(_year, _month))
    16. return true;
    17. else
    18. return false;
    19. }

                          

    加一个负数会报错,我们只需在+=里面进行调整就行,因为+是通过+=实现的

    1. Date& Date::operator+=(int day)
    2. {
    3. if (day < 0)
    4. {
    5. return *this -= -day;
    6. }
    7. _day += day;
    8. while (_day > GetMonthDay(_year, _month))
    9. {
    10. _day -= GetMonthDay(_year, _month);
    11. _month++;
    12. if (_month == 13)
    13. {
    14. _month = 1;
    15. _year ++;
    16. }
    17. }
    18. return *this;
    19. }

     

    同理对-=也修改,如果天数小于0,-=之后 会因为负负得正,给加几天,我们此时调整一下即可

    实现Cout运算符重载 

    C++ cout和cin能自动识别的原因:

    1.库里面写好了运算符重载

    2.自动识别类型,它们构成重载函数 

    运算符重载:让自定义类型对象可以用运算符,转换成调用这个重载函数

    函数重载:支持函数名相同的函数同时存在

    虽然俩者都是重载,但它们俩者没有关系

    但如果这样使用cout和cin会报错

     此时我们自己在类里面写运算重载符就可以解决这个问题

    cout是ostream类型对象,cin是istream类型对象

    1. void Date::operator<<(ostream& out)
    2. {
    3. out << _year << "-" << _month << _day;
    4. }

    此时如果写成这个样子,还是会报错

    但这样可以

     运算符有多个操作数的时候,第一个参数是左操作数,第二个参数是右操作数

    d1是第一个操作数(左操作数),cout是第二个操作数 (右操作数)

    cout<

    若想通过cout<

    此时把该运算符重载写到外面,当作一个函数,不能当成员函数使用,out就会是第一个操作数

     但会有一个缺陷,私有变量无法访问

     这里可以通过友元进行修改

    此时就可以访问这些私有成员

     但此时这样写又会不支持

     这里需要返回值,返回值就是cout,这样才能连续的插入

    此时可正常打印

     这个函数可能会被频繁调用,可能输出多行,因此搞成内联函数最好

     但是此时声明在.h定义在.cpp,声明和定义分离,链接时报错

    直接在.h里面定义好就行 

    实现Cin运算符重载 

    cin是istream类型对象,流提取,cout不需要改变Date,但Cin需要改变Date

    因为这是要从流里面提取出年月日参数,放到日期里面

     

    但此时输入非法日期不报错

     此时在加个判断

    根据日期算星期 

     以1年1月1日星期六为参考对象,输入一个日期后,俩日期相减,然后对7取模就行

    0相当于周天,1-5对应周一到周六

    1. void DateSwap()
    2. {
    3. const char* WeekDayToStr[] = { "周一","周二","周三","周四","周五","周六","周日" };
    4. Date d1;
    5. Date start(1, 1, 1);
    6. cout << "请输入日期";
    7. cin >> d1;
    8. int n = d1 - start;
    9. int weekDay = 0;
    10. weekDay += n;
    11. cout << WeekDayToStr[ weekDay % 7] << endl;
    12. }

    修改后完整代码  

    Date.h 

    1. #include
    2. #include
    3. using namespace std;
    4. class Date
    5. {
    6. friend ostream& operator<<(ostream& out, const Date& d);
    7. friend istream& operator>>(istream& in, Date& d);
    8. public:
    9. // 获取某年某月的天数
    10. int GetMonthDay(int year, int month)
    11. {
    12. static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    13. int day = days[month];
    14. if (month == 2
    15. && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
    16. {
    17. day += 1;
    18. }
    19. return day;
    20. }
    21. Date(int year = 1900, int month = 1, int day = 1)
    22. {
    23. _year = year;
    24. _month = month;
    25. _day = day;
    26. if (!CheckDate())
    27. {
    28. Print();
    29. cout << "日期非法" << endl;
    30. }
    31. }
    32. bool CheckDate()
    33. {
    34. if (_year >= 1 && _month < 13 && _month>0 && _day > 0 && _day <= GetMonthDay(_year, _month))
    35. return true;
    36. else
    37. return false;
    38. }
    39. void Print();
    40. bool operator==(const Date& d);
    41. bool operator!=(const Date& d);
    42. bool operator>(const Date& d);
    43. bool operator<(const Date& d);
    44. bool operator>=(const Date& d);
    45. bool operator<=(const Date& d);
    46. Date operator+(int day);
    47. Date& operator++();//默认是前置++,返回+完后的值,用引用返回
    48. Date operator++(int i);//后前置++,里面要写一个参数,这里的参数可以不用形参接收,括号里直接写int就行,但加了参数也无所谓,这里的参数只是为了区分
    49. //C++为了区分前后置++,使用重载进行区分,后置++重载增加一个int参数跟前置构成函数重载进行区分
    50. Date& operator+=(int day);
    51. Date operator-(int day);
    52. Date& operator-= (int day);
    53. Date& operator--();
    54. Date operator--(int);
    55. int operator-(const Date& d);
    56. private:
    57. int _year;
    58. int _month;
    59. int _day;
    60. };
    61. inline ostream& operator<<(ostream& out, const Date& d)
    62. {
    63. out << d._year <<"年" << d._month<< "月" << d._day<<"日" << endl;
    64. return out;
    65. }
    66. inline istream& operator>>(istream & in, Date & d)
    67. {
    68. assert(d.CheckDate());
    69. in >> d._year >> d._month >> d._day;
    70. return in;
    71. }
    72. void DateSwap();

    Date.cpp 

    1. #include"date.h"
    2. bool Date::operator==(const Date& d)
    3. {
    4. return _year == d._year &&
    5. _month == d._month &&
    6. _day == d._day;
    7. }
    8. bool Date::operator!=(const Date& d)
    9. {
    10. return !(*this == d);
    11. }
    12. bool Date::operator>(const Date& d)
    13. {
    14. if (_year > d._year)
    15. return true;
    16. else if (_year == d._year && _month > d._month)
    17. {
    18. return true;
    19. }
    20. else if (_year == d._year && _month == d._month && _day > d._day)
    21. {
    22. return true;
    23. }
    24. else
    25. return false;
    26. }
    27. bool Date::operator<(const Date& d)
    28. {
    29. return !(*this >= d);
    30. }
    31. bool Date::operator>=(const Date& d)
    32. {
    33. return (*this > d) || (*this == d);
    34. }
    35. bool Date::operator<=(const Date& d)
    36. {
    37. return !(*this > d);
    38. }
    39. // 自身要改变
    40. Date& Date::operator+=(int day)
    41. {
    42. if (day < 0)
    43. {
    44. return *this -= -day;
    45. }
    46. _day += day;
    47. while (_day > GetMonthDay(_year, _month))
    48. {
    49. _day -= GetMonthDay(_year, _month);
    50. _month++;
    51. if (_month == 13)
    52. {
    53. _month = 1;
    54. _year ++;
    55. }
    56. }
    57. return *this;
    58. }
    59. //自身不改变
    60. Date Date::operator+(int day)
    61. {
    62. Date ret(*this);//拷贝构造
    63. //Date ret= *this;在这里,这条语句是拷贝构造,拿*this初始化ret,已经存在的对线才是赋值
    64. ret += day;
    65. return ret;//传值返回的时候,会生成一份拷贝
    66. }
    67. void Date::Print()
    68. {
    69. cout << _year<<"/" << _month<<"/"<<_day << endl;
    70. }
    71. Date& Date::operator++()//前置
    72. {
    73. *this += 1;
    74. return *this;
    75. }
    76. Date Date::operator++(int)//后置,返回++之前的值
    77. {
    78. Date tmp(*this);
    79. *this += 1;
    80. return tmp;
    81. }
    82. Date& Date::operator-= (int day)
    83. {
    84. if (day < 0)
    85. {
    86. return *this += -day;
    87. }
    88. _day -= day;
    89. while (_day <= 0)
    90. {
    91. --_month;
    92. if (_month == 0)
    93. {
    94. --_year;
    95. _month = 12;
    96. }
    97. _day += GetMonthDay(_year,_month);
    98. }
    99. return *this;
    100. }
    101. Date Date::operator-(int day)
    102. {
    103. Date ret = *this;
    104. ret -= day;
    105. return ret;
    106. }
    107. Date& Date::operator--()//前置--
    108. {
    109. *this -= 1;
    110. return *this;
    111. }
    112. Date Date::operator--(int)//后置--
    113. {
    114. Date tmp = *this;
    115. *this -= 1;
    116. return tmp;
    117. }
    118. int Date::operator-(const Date& d)//日期相减
    119. {
    120. int flag = 1;
    121. Date max = *this;
    122. Date min = d;
    123. if (*this < d)
    124. {
    125. min = *this;
    126. max = d;
    127. flag = -1;
    128. }
    129. int n = 0;
    130. while (min != max)
    131. {
    132. ++min;
    133. ++n;
    134. }
    135. return n*flag;
    136. }
    137. void DateSwap()
    138. {
    139. const char* WeekDayToStr[] = { "周一","周二","周三","周四","周五","周六","周日" };
    140. Date d1;
    141. Date start(1, 1, 1);
    142. cout << "请输入日期";
    143. cin >> d1;
    144. int n = d1 - start;
    145. int weekDay = 0;
    146. weekDay += n;
    147. cout << WeekDayToStr[ weekDay % 7] << endl;
    148. }
    149. //void Date::operator<<(ostream& out)
    150. //{
    151. // out << _year << "-" << _month <<"-" << _day;
    152. //}

    const成员

     

    这种情况下会报错 ,会把const Date转换为Date

    这是因为this指针在传参的时候是这样的

    参数里的const修饰this指针本身 

    d1.Print();传参的时候是将d1的地址传过去,&d1,类型是Date*

    d2.Print();&d2 传不过去,因为传过去的是const Date*类型,而形参是Date*类型

    d1

     

     d1

    d2

    如果要改变这种错误,就要给this加上const,Date *const this变为const Date *const this

    把const加在这个位置

     但是对于d1,本来是Date *const this变为了const Date *const this 把权限缩小了,这样d1就不能给赋值了

     取地址及const取地址操作符重载

     权限可以缩小,平移,不能放大

    这里可以写俩个Print,构成函数重载

     

     编译器在调用的时候会自动匹配,当取地址情况下需要它们同时存在

    1. Date* operator&()
    2. {
    3. return this;
    4. }
    5. const Date* operator&()const
    6. {
    7. return this;
    8. }

    一个返回Date *,一个返回const Date *

     调用相对应的

    如果不写编译器会自动生成

     

     这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容

    如果不想让别人取地址,一般自己写一个,返回nullptr即可

    习题  计算日期到天数转换 

    计算日期到天数转换__牛客网 (nowcoder.com)

    1. #include
    2. using namespace std;
    3. int main(){
    4. int year,month,day;
    5. cin>>year>>month>>day;
    6. int monthDays[13]={0,31,59,90,120,151,181,212,243,273,304,334,365};
    7. int n=monthDays[month-1]+day;
    8. if(month>2&&((year%4==0&&year%100!=0)||(year%400==0)))
    9. n+=1;
    10. cout<
    11. return 0;
    12. }

  • 相关阅读:
    pdf怎么转换成jpg或png格式的图片?
    Ubuntu升级自带的Python3版本
    python毕业设计项目源码选题(7)校园排课选课系统毕业设计毕设作品开题报告开题答辩PPT
    Map和Set的区别
    奥数与C++小学四年级(第十六题 魔法学院)
    黑产工具情报的分析方式浅析
    esp32如何获得蓝牙地址
    无胁科技-TVD每日漏洞情报-2022-11-23
    20 个提升效率的 JS 简写技巧
    Pyecharts绘制动态地图
  • 原文地址:https://blog.csdn.net/weixin_49449676/article/details/126591571