C++ 允许在同一作用域中的某个函数运算符指定多个定义,分别称为函数重载运算符重载。 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。 当您调用一个重载函数重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策

C++ 中的函数重载

在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
下面的实例中,同名函数print()被用于输出不同的数据类型:

  1. #include <iostream>
  2. using namespace std;
  3. class printData
  4. {
  5. public:
  6. void print(int i) {
  7. cout << "整数为: " << i << endl;
  8. }
  9. void print(double f) {
  10. cout << "浮点数为: " << f << endl;
  11. }
  12. void print(char c[]) {
  13. cout << "字符串为: " << c << endl;
  14. }
  15. };
  16. int main(void)
  17. {
  18. printData pd;
  19. pd.print(5); // 输出整数
  20. pd.print(500.263); // 输出浮点数
  21. char c[] = "Hello C++";
  22. pd.print(c); // 输出字符串
  23. return 0;
  24. }
  25. /*
  26. 整数为: 5
  27. 浮点数为: 500.263
  28. 字符串为: Hello C++
  29. */

C++ 中的运算符重载

您可以重定义或重载大部分 C++ 内置的运算符。这样,您就能使用自定义类型的运算符。
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。

  1. Box operator+(const Box&);

声明加法运算符用于把两个 Box 对象相加,返回最终的 Box 对象。大多数的重载运算符可被定义为普通的非成员函数或者被定义为类成员函数。如果我们定义上面的函数为类的非成员函数,那么我们需要为每次操作传递两个参数,如下所示:

  1. Box operator+(const Box&, const Box&);

下面的实例使用成员函数演示了运算符重载的概念。在这里,对象作为参数进行传递,对象的属性使用this运算符进行访问,如下所示:

  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5. public:
  6. double getVolume(void)
  7. {
  8. return length * breadth * height;
  9. }
  10. void setLength( double len )
  11. {
  12. length = len;
  13. }
  14. void setBreadth( double bre )
  15. {
  16. breadth = bre;
  17. }
  18. void setHeight( double hei )
  19. {
  20. height = hei;
  21. }
  22. // 重载 + 运算符,用于把两个 Box 对象相加
  23. Box operator+(const Box& b)
  24. {
  25. Box box;
  26. box.length = this->length + b.length;
  27. box.breadth = this->breadth + b.breadth;
  28. box.height = this->height + b.height;
  29. return box;
  30. }
  31. private:
  32. double length; // 长度
  33. double breadth; // 宽度
  34. double height; // 高度
  35. };
  36. int main( )
  37. {
  38. Box Box1; // 声明 Box1,类型为 Box
  39. Box Box2; // 声明 Box2,类型为 Box
  40. Box Box3; // 声明 Box3,类型为 Box
  41. double volume = 0.0; // 把体积存储在该变量中
  42. // Box1 详述
  43. Box1.setLength(6.0);
  44. Box1.setBreadth(7.0);
  45. Box1.setHeight(5.0);
  46. // Box2 详述
  47. Box2.setLength(12.0);
  48. Box2.setBreadth(13.0);
  49. Box2.setHeight(10.0);
  50. // Box1 的体积
  51. volume = Box1.getVolume();
  52. cout << "Volume of Box1 : " << volume <<endl;
  53. // Box2 的体积
  54. volume = Box2.getVolume();
  55. cout << "Volume of Box2 : " << volume <<endl;
  56. // 把两个对象相加,得到 Box3
  57. Box3 = Box1 + Box2;
  58. // Box3 的体积
  59. volume = Box3.getVolume();
  60. cout << "Volume of Box3 : " << volume <<endl;
  61. return 0;
  62. }
  63. /*
  64. Volume of Box1 : 210
  65. Volume of Box2 : 1560
  66. Volume of Box3 : 5400
  67. */

可重载运算符/不可重载运算符

可重载的运算符列表

双目算术运算符 + (加)
- (减)
* (乘)
/ (除)
% (取模)
赋值运算符 =
+=
-=
*=
/=
%=
<<=
>>=
&=
|=
^=
关系运算符 == (等于)
!= (不等于)
< (小于)
> (大于)
<= (小于等于)
>= (大于等于)
逻辑运算符 && (逻辑与)
|| (逻辑或)
! (逻辑非)
位运算符 & (按位与)
| (按位或)
~ (按位取反)
^ (按位异或)
<< (左移)
>> (右移)
单目运算符 + (正)
- ( 负)
* (指针)
& (取地址)
自增自减运算符 ++ (自增)
— (自减)
空间申请与释放 new
delete
new[]
delete[]
其他运算符 () (函数调用)
-> (成员访问)
, (逗号)
[] (下标)

不可重载的运算符列表

  • . 成员访问运算符
  • . -> 成员指针访问运算符
  • :: 域运算符
  • sizeof 长度运算符
  • ?: 条件运算符
  • 预处理符号

运算符重载实例

下面提供了各种运算符重载的实例,帮助您更好地理解重载的概念。

一元运算符重载

一元运算符只对一个操作数进行操作,下面是一元运算符的实例:

  • 递增运算符( ++ )和递减运算符( — )
  • 一元减运算符,即负号( - )
  • 逻辑非运算符( ! )

一元运算符通常出现在它们所操作的对象的左边,比如 !obj、-obj 和 ++obj,但有时它们也可以作为后缀,比如 obj++ 或 obj—。
下面的实例演示了如何重载一元减运算符( - )

  1. #include <iostream>
  2. using namespace std;
  3. class Distance
  4. {
  5. private:
  6. int feet; // 0 到无穷
  7. int inches; // 0 到 12
  8. public:
  9. // 所需的构造函数
  10. Distance()
  11. {
  12. feet = 0;
  13. inches = 0;
  14. }
  15. Distance(int f, int i)
  16. {
  17. feet = f;
  18. inches = i;
  19. }
  20. // 重载负运算符( - )
  21. Distance operator-()
  22. {
  23. feet = -feet;
  24. inches = -inches;
  25. return Distance(feet, inches);
  26. }
  27. // 显示距离的方法
  28. void displayDistance()
  29. {
  30. cout << "F: " << this->feet << " I:" << inches << endl;
  31. }
  32. };
  33. int main()
  34. {
  35. Distance D1(11, 10), D2(-5, 11);
  36. -D1; // 取相反数
  37. D1.displayDistance(); // 距离 D1
  38. -D2; // 取相反数
  39. D2.displayDistance(); // 距离 D2
  40. return 0;
  41. }
  42. /*
  43. F: -11 I:-10
  44. F: 5 I:-11
  45. */

重载单目运算符++(或 —)作为前缀和后缀:
前缀与后缀重载的语法格式是不同的。

  1. #include <iostream>
  2. using namespace std;
  3. class Complex {
  4. private:
  5. double i;
  6. double j;
  7. public:
  8. Complex(int = 0, int = 0);
  9. void display();
  10. Complex operator ++(); //前缀自增
  11. Complex operator ++(int); //后缀自增,参数需要加int
  12. };
  13. Complex::Complex(int a, int b) {
  14. i = a;
  15. j = b;
  16. }
  17. void Complex::display() {
  18. cout << i << '+' << j << 'i' << endl;
  19. }
  20. Complex Complex::operator ++() {
  21. ++i;
  22. ++j;
  23. return *this;
  24. }
  25. Complex Complex::operator ++(int) {
  26. Complex temp =*this;
  27. ++*this;
  28. return temp;
  29. }
  30. int main()
  31. {
  32. Complex comnum1(2,2), comnum2,comnum3;
  33. cout << "自增计算前:" << endl;
  34. cout << "comnum1:";
  35. comnum1.display();
  36. cout << "comnum2:";
  37. comnum2.display();
  38. cout << "comnum3:";
  39. comnum3.display();
  40. cout << endl;
  41. cout << "前缀自增计算后:" << endl;
  42. comnum2 = ++comnum1;
  43. cout << "comnum1:";
  44. comnum1.display();
  45. cout << "comnum2:";
  46. comnum2.display();
  47. cout << endl;
  48. cout << "后缀自增计算后:" << endl;
  49. comnum3 = comnum1++;
  50. cout << "comnum1:";
  51. comnum1.display();
  52. cout << "comnum3:";
  53. comnum3.display();
  54. return 0;
  55. }
  56. /*
  57. 自增计算前:
  58. comnum1:2+2i
  59. comnum2:0+0i
  60. comnum3:0+0i
  61. 前缀自增计算后:
  62. comnum1:3+3i
  63. comnum2:3+3i
  64. 后缀自增计算后:
  65. comnum1:4+4i
  66. comnum3:3+3i
  67. */

二元运算符重载

二元运算符需要两个参数,下面是二元运算符的实例。我们平常使用的加运算符( + )、减运算符( - )、乘运算符( * )和除运算符( / )都属于二元运算符。就像加(+)运算符。
下面的实例演示了如何重载加运算符( + )。类似地,您也可以尝试重载减运算符( - )和除运算符( / )。

  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5. double length; // 长度
  6. double breadth; // 宽度
  7. double height; // 高度
  8. public:
  9. double getVolume(void)
  10. {
  11. return length * breadth * height;
  12. }
  13. void setLength( double len )
  14. {
  15. length = len;
  16. }
  17. void setBreadth( double bre )
  18. {
  19. breadth = bre;
  20. }
  21. void setHeight( double hei )
  22. {
  23. height = hei;
  24. }
  25. // 重载 + 运算符,用于把两个 Box 对象相加
  26. Box operator+(const Box& b)
  27. {
  28. Box box;
  29. box.length = this->length + b.length;
  30. box.breadth = this->breadth + b.breadth;
  31. box.height = this->height + b.height;
  32. return box;
  33. }
  34. };
  35. int main( )
  36. {
  37. Box Box1; // 声明 Box1,类型为 Box
  38. Box Box2; // 声明 Box2,类型为 Box
  39. Box Box3; // 声明 Box3,类型为 Box
  40. double volume = 0.0; // 把体积存储在该变量中
  41. // Box1 详述
  42. Box1.setLength(6.0);
  43. Box1.setBreadth(7.0);
  44. Box1.setHeight(5.0);
  45. // Box2 详述
  46. Box2.setLength(12.0);
  47. Box2.setBreadth(13.0);
  48. Box2.setHeight(10.0);
  49. // Box1 的体积
  50. volume = Box1.getVolume();
  51. cout << "Volume of Box1 : " << volume <<endl;
  52. // Box2 的体积
  53. volume = Box2.getVolume();
  54. cout << "Volume of Box2 : " << volume <<endl;
  55. // 把两个对象相加,得到 Box3
  56. Box3 = Box1 + Box2;
  57. // Box3 的体积
  58. volume = Box3.getVolume();
  59. cout << "Volume of Box3 : " << volume <<endl;
  60. return 0;
  61. }
  62. /*
  63. Volume of Box1 : 210
  64. Volume of Box2 : 1560
  65. Volume of Box3 : 5400
  66. */

对实例进行改写,以非成员函数的方式重载运算符 +

  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5. double length; // 长度
  6. double breadth; // 宽度
  7. double height; // 高度
  8. public:
  9. double getVolume(void)
  10. {
  11. return length * breadth * height;
  12. }
  13. void setLength( double len )
  14. {
  15. length = len;
  16. }
  17. void setBreadth( double bre )
  18. {
  19. breadth = bre;
  20. }
  21. void setHeight( double hei )
  22. {
  23. height = hei;
  24. }
  25. /**
  26. * 改写部分 2018.09.05
  27. * 重载 + 运算符,用于把两个 Box 对象相加
  28. * 因为其是全局函数,对应的参数个数为2。
  29. * 当重载的运算符函数是全局函数时,需要在类中将该函数声明为友员。
  30. */
  31. friend Box operator+(const Box& a, const Box& b);
  32. };
  33. Box operator+(const Box& a, const Box& b)
  34. {
  35. Box box;
  36. box.length = a.length + b.length;
  37. box.breadth = a.breadth + b.breadth;
  38. box.height = a.height + b.height;
  39. // cout << box.length << "--" << box.breadth << "--" << box.height << endl;
  40. return box;
  41. }
  42. // 程序的主函数
  43. int main( )
  44. {
  45. Box Box1; // 声明 Box1,类型为 Box
  46. Box Box2; // 声明 Box2,类型为 Box
  47. Box Box3; // 声明 Box3,类型为 Box
  48. double volume = 0.0; // 把体积存储在该变量中
  49. // Box1 详述
  50. Box1.setLength(6.0);
  51. Box1.setBreadth(7.0);
  52. Box1.setHeight(5.0);
  53. // Box2 详述
  54. Box2.setLength(12.0);
  55. Box2.setBreadth(13.0);
  56. Box2.setHeight(10.0);
  57. // Box1 的体积
  58. volume = Box1.getVolume();
  59. cout << "Volume of Box1 : " << volume <<endl;
  60. // Box2 的体积
  61. volume = Box2.getVolume();
  62. cout << "Volume of Box2 : " << volume <<endl;
  63. // 把两个对象相加,得到 Box3
  64. Box3 = Box1 + Box2;
  65. // Box3 的体积
  66. volume = Box3.getVolume();
  67. cout << "Volume of Box3 : " << volume <<endl;
  68. return 0;
  69. }
  70. /*
  71. Volume of Box1 : 210
  72. Volume of Box2 : 1560
  73. Volume of Box3 : 5400
  74. */

当 2 个对象相加时是没有顺序要求的,但要重载 + 让其与一个数字相加则有顺序要求,可以通过加一个友元函数使另一个顺序的输入合法。

  1. #include<iostream>
  2. using namespace std;
  3. class A
  4. {
  5. private:
  6. int a;
  7. public:
  8. A();
  9. A(int n);
  10. A operator+(const A & obj);
  11. A operator+(const int b);
  12. friend A operator+(const int b, A obj);
  13. void display();
  14. } ;
  15. A::A()
  16. {
  17. a=0;
  18. }
  19. A::A(int n)//构造函数
  20. {
  21. a=n;
  22. }
  23. A A::operator +(const A& obj)//重载+号用于 对象相加
  24. {
  25. return this->a+obj.a;
  26. }
  27. A A::operator+(const int b)//重载+号用于 对象与数相加
  28. {
  29. return A(a+b);
  30. }
  31. A operator+(const int b, A obj)
  32. {
  33. return obj+b; //友元函数调用第二个重载+的成员函数 相当于 obj.operator+(b);
  34. }
  35. void A::display()
  36. {
  37. cout<<a<<endl;
  38. }
  39. int main ()
  40. {
  41. A a1(1);
  42. A a2(2);
  43. A a3,a4,a5;
  44. a1.display();
  45. a2.display();
  46. int m=1;
  47. a3=a1+a2; //可以交换顺序,相当月a3=a1.operator+(a2);
  48. a3.display();
  49. a4=a1+m; //因为加了个友元函数所以也可以交换顺序了。
  50. a4.display();
  51. a5=m+a1;
  52. a5.display();
  53. }
  54. /*
  55. 1
  56. 2
  57. 3
  58. 2
  59. 2
  60. */

关系运算符重载

C++ 语言支持各种关系运算符( < 、 > 、 <= 、 >= 、 == 等等),它们可用于比较 C++ 内置的数据类型。
您可以重载任何一个关系运算符,重载后的关系运算符可用于比较类的对象。
下面的实例演示了如何重载 < 运算符,类似地,您也可以尝试重载其他的关系运算符。

  1. #include <iostream>
  2. using namespace std;
  3. class Distance
  4. {
  5. private:
  6. int feet; // 0 到无穷
  7. int inches; // 0 到 12
  8. public:
  9. // 所需的构造函数
  10. Distance(){ feet = 0; inches = 0; }
  11. Distance(int f, int i){
  12. feet = f;
  13. inches = i;
  14. }
  15. // 显示距离的方法
  16. void displayDistance()
  17. {
  18. cout << "F: " << feet << " I:" << inches <<endl;
  19. }
  20. // 重载负运算符( - )
  21. Distance operator- ()
  22. {
  23. feet = -feet;
  24. inches = -inches;
  25. return Distance(feet, inches);
  26. }
  27. // 重载小于运算符( < )
  28. bool operator <(const Distance& d)
  29. {
  30. if(feet < d.feet)
  31. {
  32. return true;
  33. }
  34. if(feet == d.feet && inches < d.inches)
  35. {
  36. return true;
  37. }
  38. return false;
  39. }
  40. };
  41. int main()
  42. {
  43. Distance D1(11, 10), D2(5, 11);
  44. if( D1 < D2 )
  45. {
  46. cout << "D1 is less than D2 " << endl;
  47. }
  48. else
  49. {
  50. cout << "D2 is less than D1 " << endl;
  51. }
  52. return 0;
  53. }
  54. /*
  55. D2 is less than D1
  56. */

输入/输出运算符重载

C++ 能够使用流提取运算符 >> 和流插入运算符 << 来输入和输出内置的数据类型。您可以重载流提取运算符和流插入运算符来操作对象等用户自定义的数据类型。
在这里,有一点很重要,我们需要把运算符重载函数声明为类的友元函数,这样我们就能不用创建对象而直接调用函数。
下面的实例演示了如何重载提取运算符 >> 和插入运算符 <<。

  1. #include <iostream>
  2. using namespace std;
  3. class Distance
  4. {
  5. private:
  6. int feet; // 0 到无穷
  7. int inches; // 0 到 12
  8. public:
  9. // 所需的构造函数
  10. Distance()
  11. {
  12. feet = 0;
  13. inches = 0;
  14. }
  15. Distance(int f, int i)
  16. {
  17. feet = f;
  18. inches = i;
  19. }
  20. friend istream &operator>>(istream &input, Distance &D)
  21. {
  22. input >> D.feet >> D.inches >> D.inches;
  23. return input;
  24. }
  25. friend ostream &operator<<(ostream &output, const Distance &D)
  26. {
  27. output << "F : " << D.feet << " I : " << D.inches;
  28. return output;
  29. }
  30. };
  31. int main()
  32. {
  33. Distance D1(11, 10), D2(5, 11), D3;
  34. cout << "Enter the value of object : " << endl;
  35. cin >> D3;
  36. cout << "First Distance : " << D1 << endl;
  37. cout << "Second Distance :" << D2 << endl;
  38. cout << "Third Distance :" << D3 << endl;
  39. return 0;
  40. }
  41. /*
  42. Enter the value of object :
  43. 10
  44. 20
  45. First Distance : F : 11 I : 10
  46. Second Distance :F : 5 I : 11
  47. Third Distance :F : 10 I : 20
  48. */

习惯上人们是使用 cin>> 和 cout<< 的,得使用友元函数来重载运算符
如果使用成员函数来重载会出现 d1<<cout 这种不自然的代码。
下面这个实例展示了如果运用成员函数来重载会出现的情况 d1<<cout

  1. #include <iostream>
  2. using namespace std;
  3. class Distance
  4. {
  5. private:
  6. int feet; // 0 到无穷
  7. int inches; // 0 到 12
  8. public:
  9. // 所需的构造函数
  10. Distance()
  11. {
  12. feet = 0;
  13. inches = 0;
  14. }
  15. Distance(int f, int i)
  16. {
  17. feet = f;
  18. inches = i;
  19. }
  20. ostream &operator<<(ostream &os)
  21. {
  22. os << "英寸:" << feet << "\n英尺:" << inches << endl;
  23. return os;
  24. }
  25. };
  26. int main()
  27. {
  28. Distance d1(20, 18);
  29. d1 << cout; //相当于d1.operator<<(cout)
  30. }
  31. /*
  32. 英寸:20
  33. 英尺:18
  34. */

++ 和 — 运算符重载

递增运算符( ++ )和递减运算符( — )是 C++ 语言中两个重要的一元运算符。
下面的实例演示了如何重载递增运算符( ++ ),包括前缀和后缀两种用法。类似地,您也可以尝试重载递减运算符( — )。

  1. #include <iostream>
  2. using namespace std;
  3. class Time
  4. {
  5. private:
  6. int hours; // 0 到 23
  7. int minutes; // 0 到 59
  8. public:
  9. // 所需的构造函数
  10. Time()
  11. {
  12. hours = 0;
  13. minutes = 0;
  14. }
  15. Time(int h, int m)
  16. {
  17. hours = h;
  18. minutes = m;
  19. }
  20. // 显示时间的方法
  21. void displayTime()
  22. {
  23. cout << "H: " << hours << " M:" << minutes << endl;
  24. }
  25. // 重载前缀递增运算符( ++ )
  26. Time operator++()
  27. {
  28. ++minutes; // 对象加 1
  29. if (minutes >= 60)
  30. {
  31. ++hours;
  32. minutes -= 60;
  33. }
  34. return Time(hours, minutes);
  35. }
  36. // 重载后缀递增运算符( ++ )
  37. Time operator++(int)
  38. {
  39. Time T(hours, minutes); // 保存原始值
  40. // 对象加 1
  41. ++minutes;
  42. if (minutes >= 60)
  43. {
  44. ++hours;
  45. minutes -= 60;
  46. }
  47. return T; // 返回旧的原始值
  48. }
  49. };
  50. int main()
  51. {
  52. Time T1(11, 59), T2(10, 40);
  53. ++T1; // T1 加 1
  54. T1.displayTime(); // 显示 T1
  55. ++T1; // T1 再加 1
  56. T1.displayTime(); // 显示 T1
  57. T2++; // T2 加 1
  58. T2.displayTime(); // 显示 T2
  59. T2++; // T2 再加 1
  60. T2.displayTime(); // 显示 T2
  61. return 0;
  62. }
  63. /*
  64. H: 12 M:0
  65. H: 12 M:1
  66. H: 10 M:41
  67. H: 10 M:42
  68. */

⚠️注意: 注意,int 在 括号内是为了向编译器说明这是一个后缀形式,而不是表示整数。

  • 前缀形式重载调用 Check operator ++ ()
  • 后缀形式重载调用 operator ++ (int)

++ 重载

  1. #include <iostream>
  2. using namespace std;
  3. class Check
  4. {
  5. private:
  6. int i;
  7. public:
  8. Check(): i(0) { }
  9. Check operator ++ ()
  10. {
  11. Check temp;
  12. temp.i = ++i;
  13. return temp;
  14. }
  15. // 括号中插入 int 表示后缀
  16. Check operator ++ (int)
  17. {
  18. Check temp;
  19. temp.i = i++;
  20. return temp;
  21. }
  22. void Display()
  23. { cout << "i = "<< i <<endl; }
  24. };
  25. int main()
  26. {
  27. Check obj, obj1;
  28. obj.Display();
  29. obj1.Display();
  30. // 调用运算符函数,然后将 obj 的值赋给 obj1
  31. obj1 = ++obj;
  32. obj.Display();
  33. obj1.Display();
  34. // 将 obj 赋值给 obj1, 然后再调用运算符函数
  35. obj1 = obj++;
  36. obj.Display();
  37. obj1.Display();
  38. return 0;
  39. }
  40. /*
  41. i = 0
  42. i = 0
  43. i = 1
  44. i = 1
  45. i = 2
  46. i = 1
  47. */

— 重载

  1. #include <iostream>
  2. using namespace std;
  3. class Check
  4. {
  5. private:
  6. int i;
  7. public:
  8. Check(): i(3) { }
  9. Check operator -- ()
  10. {
  11. Check temp;
  12. temp.i = --i;
  13. return temp;
  14. }
  15. // 括号中插入 int 表示后缀
  16. Check operator -- (int)
  17. {
  18. Check temp;
  19. temp.i = i--;
  20. return temp;
  21. }
  22. void Display()
  23. { cout << "i = "<< i <<endl; }
  24. };
  25. int main()
  26. {
  27. Check obj, obj1;
  28. obj.Display();
  29. obj1.Display();
  30. // 调用运算符函数,然后将 obj 的值赋给 obj1
  31. obj1 = --obj;
  32. obj.Display();
  33. obj1.Display();
  34. // 将 obj 赋值给 obj1, 然后再调用运算符函数
  35. obj1 = obj--;
  36. obj.Display();
  37. obj1.Display();
  38. return 0;
  39. }
  40. /*
  41. i = 3
  42. i = 3
  43. i = 2
  44. i = 2
  45. i = 1
  46. i = 2
  47. */

递增和递减运算符重载

  • 递增和递减一般是改变对象的状态,所以一般是重载为成员函数。
  • 重载递增递减,一定要和指针的递增递减区分开。因为这里的重载操作的是对象,而不是指针(由于指针是内置类型,指针的递增递减是无法重载的),所以一般情况的递增递减是操作对象内部的成员变量。
  • 递增和递减分为前置和后置情况,a = ++b;(前置), a = b++;(后置)。因为符号一样,所以给后置版本加一个int形参作为区分,这个形参是0,但是在函数体中是用不到的,只是为了区分前置后置。例如: ```cpp

    include

    include

    include

    include

using namespace std;

// 例如这里的重载递增就是为了增加 num 的值 class Calculation { public:
int num;

  1. //前置递增就是增加当前对象的 num 的值,并且返回当前对象
  2. Calculation operator++(){
  3. num++;
  4. return *this;
  5. }
  6. //后置递增就是增加当前对象的 num 的值,并且返回增加 num 之前的该对象
  7. Calculation operator++(int){
  8. Calculation ret = *this;
  9. ++*this; //这个会调用上面的函数,其实这里可以换成 num++;
  10. return ret;
  11. }

};

int main() { Calculation a, b; a.num = 1;

b = a++;
cout << "b1:" << b.num << endl;   // b1:1

b = ++a;
cout << "b2:" << b.num << endl;   // b1:3

return 0;

}


<a name="RWga6"></a>
### 赋值运算符重载
就像其他运算符一样,您可以重载赋值运算符( = ),用于创建一个对象,比如拷贝构造函数。<br />下面的实例演示了如何重载赋值运算符。
```cpp
#include <iostream>
using namespace std;

class Distance
{
   private:
      int feet;             // 0 到无穷
      int inches;           // 0 到 12
   public:
      // 所需的构造函数
      Distance(){
         feet = 0;
         inches = 0;
      }
      Distance(int f, int i){
         feet = f;
         inches = i;
      }
            // 显示距离的方法
      void displayDistance()
      {
         cout << "F: " << feet <<  " I:" <<  inches << endl;
      }
      void operator=(const Distance &D )
      { 
         this->feet = D.feet;
         this->inches = D.inches;
      }
};


int main()
{
   Distance D1(11, 10), D2(5, 11);

   cout << "First Distance : "; 
   D1.displayDistance();
   cout << "Second Distance :"; 
   D2.displayDistance();

   // 使用赋值运算符
   D1 = D2;
   cout << "First Distance :"; 
   D1.displayDistance();

   return 0;
}

/* 
First Distance : F: 11 I:10
Second Distance :F: 5 I:11

First Distance :F: 5 I:11 
*/


函数调用运算符 () 重载

函数调用运算符 () 可以被重载用于类的对象。当重载 () 时,您不是创造了一种新的调用函数的方式,相反地,这是创建一个可以传递任意数目参数的运算符函数。
下面的实例演示了如何重载函数调用运算符 ()。

#include <iostream>
using namespace std;

class Distance
{
private:
   int feet;   // 0 到无穷
   int inches; // 0 到 12
public:
   // 所需的构造函数
   Distance()
   {
      feet = 0;
      inches = 0;
   }
   Distance(int f, int i)
   {
      feet = f;
      inches = i;
   }
   // 显示距离的方法
   void displayDistance()
   {
      cout << "F: " << feet << " I:" << inches << endl;
   }
   // 重载函数调用运算符
   Distance operator()(int a, int b, int c)
   {
      Distance D;
      // 进行随机计算
      D.feet = a + c + 10;
      D.inches = b + c + 100;
      return D;
   }
};

int main()
{
   Distance D1(11, 10), D2;

   cout << "First Distance : ";
   D1.displayDistance();

   D2 = D1(10, 10, 10); // invoke operator()
   cout << "Second Distance :";
   D2.displayDistance();

   return 0;
}

/* 
First Distance : F: 11 I:10
Second Distance :F: 30 I:120 
*/

下标运算符 [] 重载

下标操作符 [] 通常用于访问数组元素。重载该运算符用于增强操作 C++ 数组的功能。
下面的实例演示了如何重载下标运算符 []。

#include <iostream>
using namespace std;
const int SIZE = 10;

class safearay
{
   private:
      int arr[SIZE];
   public:
      safearay() 
      {
         register int i;
         for(i = 0; i < SIZE; i++)
         {
           arr[i] = i;
         }
      }
      int& operator[](int i)
      {
          if( i > SIZE )
          {
              cout << "索引超过最大值" <<endl; 
              // 返回第一个元素
              return arr[0];
          }
          return arr[i];
      }
};


int main()
{
   safearay A;

   cout << "A[2] 的值为 : " << A[2] <<endl;
   cout << "A[5] 的值为 : " << A[5]<<endl;
   cout << "A[12] 的值为 : " << A[12]<<endl;

   return 0;
}

/* 
A[2] 的值为 : 2
A[5] 的值为 : 5
A[12] 的值为 : 索引超过最大值
0 
*/


类成员访问运算符 -> 重载

类成员访问运算符( -> )可以被重载,但它较为麻烦。它被定义用于为一个类赋予”指针”行为。运算符 -> 必须是一个成员函数。如果使用了 -> 运算符,返回类型必须是指针或者是类的对象。
运算符 -> 通常与指针引用运算符 * 结合使用,用于实现”智能指针”的功能。这些指针是行为与正常指针相似的对象,唯一不同的是,当您通过指针访问对象时,它们会执行其他的任务。比如,当指针销毁时,或者当指针指向另一个对象时,会自动删除对象。
间接引用运算符 -> 可被定义为一个一元后缀运算符。也就是说,给出一个类:

class Ptr{
   //...
   X * operator->();
};

Ptr 的对象可用于访问类 X 的成员,使用方式与指针的用法十分相似。例如:

void f(Ptr p )
{
   p->m = 10 ; // (p.operator->())->m = 10
}

语句 p->m 被解释为 (p.operator->())->m。同样地,下面的实例演示了如何重载类成员访问运算符 ->。

#include <iostream>
#include <vector>
using namespace std;

// 假设一个实际的类
class Obj
{
   static int i;
   static char j;

public:
   void f() const { cout << i++ << ": "; }
   void g() const { cout << j++ << endl; }
};

// 静态成员定义
int Obj::i = 65;
char Obj::j = 65;

// 为上面的类实现一个容器
class ObjContainer
{
   vector<Obj *> list;

public:
   void add(Obj *obj)
   {
      list.push_back(obj); // 调用向量的标准方法
   }
   friend class SmartPointer;
};

// 实现智能指针,用于访问类 Obj 的成员
class SmartPointer
{
   ObjContainer oc;
   int index;

public:
   SmartPointer(ObjContainer &objc)
   {
      oc = objc;
      index = 0;
   }

   // 返回值表示列表结束
   bool operator++() // 前缀版本
   {
      if (index >= oc.list.size() - 1)
         return false;
      if (oc.list[++index] == 0)
         return false;
      return true;
   }
   bool operator++(int) // 后缀版本
   {
      return operator++();
   }
   // 重载运算符 ->
   Obj *operator->() const
   {
      if (!oc.list[index])
      {
         cout << "Zero value";
         return (Obj *)0;
      }
      return oc.list[index];
   }
};

int main()
{
   const int size = 10;
   Obj o[size];
   ObjContainer oc;
   for (int i = 0; i < size; i++)
   {
      oc.add(&o[i]);
   }
   SmartPointer sp(oc); // 创建一个迭代器
   do
   {
      sp->f(); // 智能指针调用
      sp->g();
   } while (sp++);
   return 0;
}

/* 
65: A
66: B
67: C
68: D
69: E
70: F
71: G
72: H
73: I
74: J
*/