重载加减运算符

成员函数进行运算符重载

image.png

  1. {
  2. this->m_A = a;
  3. this->m_B = b;
  4. }
  5. //成员函数实现 + 号运算符重载
  6. Person operator+(const Person& p) {
  7. Person temp;
  8. temp.m_A = this->m_A + p.m_A;
  9. temp.m_B = this->m_B + p.m_B;
  10. return temp;
  11. }
  12. public:
  13. int m_A;
  14. int m_B;
  15. };
  16. //全局函数实现 + 号运算符重载
  17. //Person operator+(const Person& p1, const Person& p2) {
  18. // Person temp(0, 0);
  19. // temp.m_A = p1.m_A + p2.m_A;
  20. // temp.m_B = p1.m_B + p2.m_B;
  21. // return temp;
  22. //}
  23. //运算符重载 可以发生函数重载
  24. Person operator+(const Person& p2, int val)
  25. {
  26. Person temp;
  27. temp.m_A = p2.m_A + val;
  28. temp.m_B = p2.m_B + val;
  29. return temp;
  30. }
  31. void test() {
  32. Person p1(10, 10);
  33. Person p2(20, 20);
  34. //成员函数方式
  35. Person p3 = p2 + p1; //相当于 p2.operaor+(p1)
  36. cout << "mA:" << p3.m_A << " mB:" << p3.m_B << endl;
  37. Person p4 = p3 + 10; //相当于 operator+(p3,10)
  38. cout << "mA:" << p4.m_A << " mB:" << p4.m_B << endl;
  39. }
  40. int main() {
  41. test();
  42. system("pause");
  43. return 0;
  44. }

总结1:对于内置的数据类型的表达式的的运算符是不可能改变的 总结2:不要滥用运算符重载

未使用重载进行计算

  1. class Person {
  2. public:
  3. Person(int v1, int v2) {
  4. m_v1 = v1;
  5. m_v2 = v2;
  6. }
  7. int m_v1;
  8. int m_v2;
  9. Person add(Person& p) {
  10. Person temp;
  11. temp.m_v1 = this->m_v1 + p.m_v1;
  12. temp.m_v2 = this->m_v2 + p.m_v2;
  13. return temp;
  14. }
  15. };
  16. void Example() {
  17. Person p1(10,20);
  18. Person p2(30,40);
  19. p2 = p2.add(p1);
  20. cout << "P2.M_V1 = " << p2.m_v1 << endl;
  21. cout << "P2.M_V2 =" << p2.m_v2 << endl;
  22. }//实际上是一个浅拷贝

使用重载运算符

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <malloc.h>
  4. using namespace std;
  5. class Person {
  6. public:
  7. Person():m_v1(0),m_v2(0) {}
  8. Person(int v1, int v2) {
  9. m_v1 = v1;
  10. m_v2 = v2;
  11. }
  12. int m_v1;
  13. int m_v2;
  14. Person operator+ (Person& p) {
  15. Person temp;
  16. temp.m_v1 = this->m_v1 + p.m_v1;
  17. temp.m_v2 = this->m_v2 + p.m_v2;
  18. return temp;
  19. }
  20. };
  21. void Example() {
  22. Person p1(10,20);
  23. Person p2(30,40);
  24. Person p3= p2 + p1;
  25. cout << "P2.M_V1 = " << p3.m_v1 << endl;
  26. cout << "P2.M_V2 =" << p3.m_v2 << endl;
  27. }
  28. int main() {
  29. Example();
  30. return 0;
  31. }

全局重载需要两个引用

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <malloc.h>
  4. using namespace std;
  5. class Person {
  6. public:
  7. Person():m_v1(0),m_v2(0) {}
  8. Person(int v1, int v2) {
  9. m_v1 = v1;
  10. m_v2 = v2;
  11. }
  12. int m_v1;
  13. int m_v2;
  14. };
  15. Person operator+(Person& p1, Person& p2) {
  16. Person temp;
  17. temp.m_v1 = p1.m_v1 + p2.m_v1;
  18. temp.m_v2 = p1.m_v2 + p2.m_v2;
  19. return temp;
  20. }
  21. void Example() {
  22. Person p1(10,20);
  23. Person p2(30,40);
  24. Person p3= p2 + p1;
  25. cout << "P2.M_V1 = " << p3.m_v1 << endl;
  26. cout << "P2.M_V2 =" << p3.m_v2 << endl;
  27. }
  28. int main() {
  29. Example();
  30. return 0;
  31. }

重载左移运算符

一般来说不使用成员函数来重载左移运算符,因为cout在左移运算符的左边,如果重载,对象只能在右边。
所以使用全局函数来重载左移运算符。

  1. class Person {
  2. public:
  3. Person(int a,int b) {
  4. this->m_a = a;
  5. this->m_b = b;
  6. }
  7. int m_a;
  8. int m_b;
  9. };
  10. void operator<<(ostream& cout, Person& p) {
  11. cout << "m_a = " << p.m_a << " m_b = " << p.m_b;
  12. }
  13. void Example() {
  14. Person p(1, 2);
  15. cout << p;
  16. }

全局函数重载可解决问题,但是返回值是void,后面无法加入endl;
返回值改为原有的对象,也就是cout,就可以解决问题,加入return cout

  1. ostream& operator<<(ostream& cout, Person& p) {
  2. cout << "m_a = " << p.m_a << " m_b = " << p.m_b;
  3. return cout;
  4. }
  5. void Example() {
  6. Person p(1, 2);
  7. cout << p << endl;
  8. }

问题即可解决。
在实际编程规范中,成员变量一般为私有的,那全局重载就需要将全局函数变为友元

  1. class Person {
  2. friend ostream& operator<<(ostream& cout, Person& p);
  3. public:
  4. Person(int a,int b) {
  5. this->m_a = a;
  6. this->m_b = b;
  7. }
  8. private:
  9. int m_a;
  10. int m_b;
  11. };
  12. ostream& operator<<(ostream& cout, Person& p) {
  13. cout << "m_a = " << p.m_a << " m_b = " << p.m_b;
  14. return cout;
  15. }

总结:重载左移运算符配合友元可以实现输出自定义数据类型

重载自增运算符

前置自增

  1. class myInt {
  2. friend ostream& operator<<(ostream& cout, myInt& in);
  3. public:
  4. myInt() {
  5. m_int = 0;
  6. }
  7. //返回引用是为了一直对同一个对象进行递增,否则将会返回新的对象
  8. myInt& operator++() {
  9. m_int++;
  10. return *this;
  11. }
  12. private:
  13. int m_int;
  14. };
  15. ostream& operator<<(ostream& cout, myInt& in) {
  16. cout << in.m_int;
  17. return cout;
  18. }
  19. void Example() {
  20. myInt myint;
  21. cout << myint << endl;
  22. }

后置自增

  1. void operator++(int) {
  2. //int 是一个占位参数,可以用于区分前置运算符和后置运算符
  3. //先记录初始结果
  4. //再进行递增运算
  5. //然后再返回最后结果
  6. }
  1. myInt operator++(int) {
  2. //int 是一个占位参数,可以用于区分前置运算符和后置运算符
  3. myInt temp;
  4. temp = *this;
  5. this->m_int++;
  6. return temp;
  7. }
  1. class MyInteger {
  2. friend ostream& operator<<(ostream& out, MyInteger myint);
  3. public:
  4. MyInteger() {
  5. m_Num = 0;
  6. }
  7. //前置++
  8. MyInteger& operator++() {
  9. //先++
  10. m_Num++;
  11. //再返回
  12. return *this;
  13. }
  14. //后置++
  15. MyInteger operator++(int) {
  16. //先返回
  17. MyInteger temp = *this; //记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;
  18. m_Num++;
  19. return temp;
  20. }
  21. private:
  22. int m_Num;
  23. };
  24. ostream& operator<<(ostream& out, MyInteger myint) {
  25. out << myint.m_Num;
  26. return out;
  27. }
  28. //前置++ 先++ 再返回
  29. void test01() {
  30. MyInteger myInt;
  31. cout << ++myInt << endl;
  32. cout << myInt << endl;
  33. }
  34. //后置++ 先返回 再++
  35. void test02() {
  36. MyInteger myInt;
  37. cout << myInt++ << endl;
  38. cout << myInt << endl;
  39. }
  40. int main() {
  41. test01();
  42. //test02();
  43. system("pause");
  44. return 0;
  45. }

重载赋值运算符

再深浅拷贝中提到的下列问题可通过自己设计深拷贝解决:

  1. class Person {
  2. public:
  3. Person(int a) {
  4. m_age = new int(a);
  5. }
  6. ~Person() {
  7. if (m_age != NULL) {
  8. delete m_age;
  9. }
  10. }
  11. Person(const Person& p) {
  12. m_age = new int(*p.m_age);
  13. }
  14. int *m_age;
  15. };
  16. void example() {
  17. Person p1(18);
  18. Person p2(p1);
  19. cout << *p2.m_age << endl;
  20. }

但若表达式为赋值而非传参,则需要对赋值运算符进行重载

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class Person {
  5. public:
  6. Person(int a) {
  7. m_age = new int(a);
  8. }
  9. ~Person() {
  10. if (m_age != NULL) {
  11. delete m_age;
  12. }
  13. }
  14. Person& operator=(Person &p) {
  15. //如果堆区存在数据,则需要先进行delete清理
  16. if (this->m_age != NULL) {
  17. delete m_age;
  18. }
  19. this->m_age = new int(*p.m_age);
  20. //然后再进行深拷贝
  21. //要想连等成功,必须要返回一个对象
  22. //左值右值的类型相同
  23. return *this;
  24. //返回自身可以实现类型相同
  25. //this类型是Person引用
  26. }
  27. //Person(const Person& p) {
  28. // m_age = new int(*p.m_age);
  29. //}
  30. int *m_age;
  31. };
  32. void example() {
  33. Person p1(18);
  34. Person p2(20);
  35. Person p3(30);
  36. p1 = p2 = p3;
  37. cout << *p1.m_age << endl;
  38. cout << *p2.m_age << endl;
  39. cout << *p3.m_age << endl;
  40. }
  41. int main() {
  42. example();
  43. return 0;
  44. }

重载关系运算符

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class Person {
  5. public:
  6. Person(string str,int age) {
  7. this->age = age;
  8. name = str;
  9. }
  10. bool operator==(const Person& p) {
  11. if (p.age == this->age && this->name == p.name) {
  12. return true;
  13. }
  14. else return false;
  15. }
  16. bool operator!=(const Person& p) {
  17. if(p.age != this->age || this->name != p.name) {
  18. return true;
  19. }
  20. else return false;
  21. }
  22. string name;
  23. int age;
  24. };
  25. void example() {
  26. Person p1("zhang", 18);
  27. Person p2("zhang", 18);
  28. Person p3("li", 20);
  29. if (p1 != p3) {
  30. cout << "Reconstruct Complete";
  31. }
  32. }
  33. int main() {
  34. example();
  35. return 0;
  36. }

重载函数调用运算符

仿函数

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class Person {
  5. public:
  6. void operator()(string str) {
  7. cout << str << endl;
  8. }
  9. };
  10. void example() {
  11. Person print;
  12. print("Hello World!");
  13. //由于使用起来非常像函数,所以称为仿函数
  14. }
  15. int main() {
  16. example();
  17. return 0;
  18. }

仿函数非常灵活,不限于写法