C++面向对象-14-递增运算符的重载

水深无声 2023-07-03 03:19 47阅读 0赞

接着来学习递增运算符的重载,有一个变量i, i++ 这个++符号就是递增运算符。前面学习了几个运算符重载,需要明白的是,对于基本数据类型的运算,我们是不可以进行重载,例如两个int类型的数的加减乘除都不可以进行运算符的重载。我们需要使用运算符的重载是解决一些自定义的数据类型的时候。

1.基本整形数据的前置和后置递增

我们先来回顾一下整形变量前置递增和后置递增的规律。

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int a = 10;
  6. int b = 10;
  7. //前置递增
  8. cout << "++b = " << ++b << endl; // 11
  9. cout << "b = " << b << endl; //11
  10. //后置递增
  11. cout << "a++ = " << a++ << endl; // 10
  12. cout << "a = " << a << endl; // 11
  13. system("pause");
  14. return 0;
  15. }

运行结果

20200201150708396.png

总结:

前置递增:先让变量递增,在计算表达式值。

后置递增:先做表达式运算,再让变量递增。

2.需求

我们需要支持自定义一个Integer类,里面维护一个Int数据,支持使用类对象的名称进行前置递增和后置递增。

  1. #include <iostream>
  2. using namespace std;
  3. class MyInteger
  4. {
  5. private:
  6. int m_Number;
  7. public:
  8. MyInteger()
  9. {
  10. m_Number = 0;
  11. }
  12. };
  13. void test01()
  14. {
  15. MyInteger mi;
  16. cout << mi << endl;
  17. }
  18. int main()
  19. {
  20. test01();
  21. system("pause");
  22. return 0;
  23. }

需求就是我们只输入对象名称,或者mi++ 来支持输出,这个就是我们重载递增运算符的需求(上面第19行代码会报错)。

3.前置递增重载实现

这里我们是cout << 对象支持链式编程,所以我们这里需要用到前面一篇的左移运算符重载。为了实现cout在左边,我们重载都选择全局函数的方式。

先实现左移,能够输出自定义类的属性值,代码如下

  1. #include <iostream>
  2. using namespace std;
  3. class MyInteger
  4. {
  5. friend ostream & operator<<(ostream &out, MyInteger mi);
  6. private:
  7. int m_Number;
  8. public:
  9. MyInteger()
  10. {
  11. m_Number = 0;
  12. }
  13. };
  14. ostream & operator<<(ostream &out, MyInteger mi)
  15. {
  16. out << mi.m_Number;
  17. return out;
  18. }
  19. void test01()
  20. {
  21. MyInteger mi;
  22. cout << mi << endl;
  23. }
  24. int main()
  25. {
  26. test01();
  27. system("pause");
  28. return 0;
  29. }

输出值是0,接下来,考虑如何写前置递增的运算符重载。

前置递增重载实现

  1. #include <iostream>
  2. using namespace std;
  3. class MyInteger
  4. {
  5. friend ostream & operator<<(ostream &out, MyInteger mi);
  6. private:
  7. int m_Number;
  8. public:
  9. MyInteger()
  10. {
  11. m_Number = 0;
  12. }
  13. //重载前置++运算符
  14. MyInteger& operator++()
  15. {
  16. // 先进行++运算
  17. m_Number++;
  18. // 在将自身返回,返回一个引用
  19. return *this;
  20. }
  21. };
  22. ostream & operator<<(ostream &out, MyInteger mi)
  23. {
  24. out << mi.m_Number;
  25. return out;
  26. }
  27. void test01()
  28. {
  29. MyInteger mi;
  30. cout << ++mi << endl;
  31. }
  32. int main()
  33. {
  34. test01();
  35. system("pause");
  36. return 0;
  37. }

这里来分析这个重载函数

  1. //重载前置++运算符
  2. MyInteger& operator++()
  3. {
  4. // 先进行++运算
  5. m_Number++;
  6. // 在将自身返回,返回一个引用
  7. return *this;
  8. }

这里为什么要返回一个引用,而不是直接返回值

  1. //重载前置++运算符
  2. MyInteger operator++()
  3. {
  4. // 先进行++运算
  5. m_Number++;
  6. // 在将自身返回,返回一个引用
  7. return *this;
  8. }

下面我们改成返回值的方式,来测试一段代码

  1. #include <iostream>
  2. using namespace std;
  3. class MyInteger
  4. {
  5. friend ostream & operator<<(ostream &out, MyInteger mi);
  6. private:
  7. int m_Number;
  8. public:
  9. MyInteger()
  10. {
  11. m_Number = 0;
  12. }
  13. //重载前置++运算符
  14. MyInteger operator++()
  15. {
  16. // 先进行++运算
  17. m_Number++;
  18. // 在将自身返回,返回一个引用
  19. return *this;
  20. }
  21. };
  22. ostream & operator<<(ostream &out, MyInteger mi)
  23. {
  24. out << mi.m_Number;
  25. return out;
  26. }
  27. void test01()
  28. {
  29. MyInteger mi;
  30. cout << ++(++mi ) << endl;
  31. cout << mi << endl;
  32. }
  33. int main()
  34. {
  35. test01();
  36. system("pause");
  37. return 0;
  38. }

看上面代码34 35行,34行连续对一个对象做了两次自增,打印结果应该是2,运行上面代码打印对象mi的结果却是1,这个前置递增效果,和文章中开头演示的int数据类型前置递增效果不一致。所以回到重载函数,这里就需要返回一个引用,而不是返回值。

4.后置递增实现

  1. #include <iostream>
  2. using namespace std;
  3. class MyInteger
  4. {
  5. friend ostream & operator<<(ostream &out, MyInteger mi);
  6. private:
  7. int m_Number;
  8. public:
  9. MyInteger()
  10. {
  11. m_Number = 0;
  12. }
  13. //重载前置++运算符
  14. MyInteger& operator++()
  15. {
  16. // 先进行++运算
  17. m_Number++;
  18. // 在将自身返回,返回一个引用
  19. return *this;
  20. }
  21. //重载后置++运算符
  22. // 参数int是占位参数,用来区分前置还是后置,固定写法
  23. MyInteger operator++(int)
  24. {
  25. //先记录当时结果
  26. MyInteger temp = *this;
  27. //然后变量递增
  28. m_Number++;
  29. //最后返回当时记录的结果
  30. return temp;
  31. }
  32. };
  33. ostream & operator<<(ostream &out, MyInteger mi)
  34. {
  35. out << mi.m_Number;
  36. return out;
  37. }
  38. void test01()
  39. {
  40. MyInteger mi;
  41. cout << mi++ << endl;
  42. cout << mi << endl;
  43. }
  44. int main()
  45. {
  46. test01();
  47. system("pause");
  48. return 0;
  49. }

重点都在代码注释里。有了这个递增重载的思路,要写一个递减那就很简单,改一下符号就可以。

发表评论

表情:
评论列表 (有 0 条评论,47人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++面向对象-15-赋值运算符重载

    这一篇来学习赋值运算符重载,先来了解什么是赋值运算符,也就是单个等号(=)就是赋值运算符。什么时候,我们需要对赋值运算符进行重载呢?这里面离不开值拷贝的知识。   1.C+

    相关 C++面向对象-12-加号运算符重载

    这篇来学习一下运算符重载,运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。这些运算符重载,包括,加减号,左右移,关系运算符,赋值运算符和递增

    相关 C++运算符重载

    C++中预定义的运算符的操作对象只能是基本数据类型,实际上,对于很多用户自定义类型,也需要有类似的运算操作。例如:  class complex  \{   pub

    相关 C++运算符重载

    C\++中预定义的运算符的操作对象只能是基本数据类型。但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作。这时就必须在C\++中重新定义这些运算符,赋予已有运算符