• 第十六章 类和对象——运算符重载


    运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。

    一、加号运算符重载

    作用:实现两个自定义数据类型相加的运算

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

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

    总结2:不要滥用运算符重载

    二、左移运算符重载

    作用:可以输出自定义数据类型

    1.  class Person {
    2.   friend ostream& operator<<(ostream& out, Person& p);
    3.  ​
    4.  public:
    5.  ​
    6.   Person(int a, int b)
    7.   {
    8.   this->m_A = a;
    9.   this->m_B = b;
    10.   }
    11.  ​
    12.   //成员函数 实现不了 p << cout 不是我们想要的效果
    13.   //void operator<<(Person& p){
    14.   //}
    15.  ​
    16.  private:
    17.   int m_A;
    18.   int m_B;
    19.  };
    20.  ​
    21.  //全局函数实现左移重载
    22.  //ostream对象只能有一个
    23.  ostream& operator<<(ostream& out, Person& p) {
    24.   out << "a:" << p.m_A << " b:" << p.m_B;
    25.   return out;
    26.  }
    27.  ​
    28.  void test() {
    29.  ​
    30.   Person p1(10, 20);
    31.  ​
    32.   cout << p1 << "hello world" << endl; //链式编程
    33.  }
    34.  ​
    35.  int main() {
    36.  ​
    37.   test();
    38.  ​
    39.   system("pause");
    40.  ​
    41.   return 0;
    42.  }

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

    三、递增运算符重载

    作用: 通过重载递增运算符,实现自己的整型数据

    1.  class MyInteger {
    2.  ​
    3.   friend ostream& operator<<(ostream& out, MyInteger myint);
    4.  ​
    5.  public:
    6.   MyInteger() {
    7.   m_Num = 0;
    8.   }
    9.   //前置++
    10.   MyInteger& operator++() {
    11.   //先++
    12.   m_Num++;
    13.   //再返回
    14.   return *this;
    15.   }
    16.  ​
    17.   //后置++
    18.   MyInteger operator++(int) {
    19.   //先返回
    20.   MyInteger temp = *this; //记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;
    21.   m_Num++;
    22.   return temp;
    23.   }
    24.  ​
    25.  private:
    26.   int m_Num;
    27.  };
    28.  ​
    29.  ​
    30.  ostream& operator<<(ostream& out, MyInteger myint) {
    31.   out << myint.m_Num;
    32.   return out;
    33.  }
    34.  ​
    35.  ​
    36.  //前置++ 先++ 再返回
    37.  void test01() {
    38.   MyInteger myInt;
    39.   cout << ++myInt << endl;
    40.   cout << myInt << endl;
    41.  }
    42.  ​
    43.  //后置++ 先返回 再++
    44.  void test02() {
    45.  ​
    46.   MyInteger myInt;
    47.   cout << myInt++ << endl;
    48.   cout << myInt << endl;
    49.  }
    50.  ​
    51.  int main() {
    52.  ​
    53.   test01();
    54.   //test02();
    55.  ​
    56.   system("pause");
    57.  ​
    58.   return 0;
    59.  }

    总结: 前置递增返回引用,后置递增返回值。

    四、赋值运算符重载

    c++编译器至少给一个类添加4个函数

    1. 默认构造函数(无参,函数体为空)

    2. 默认析构函数(无参,函数体为空)

    3. 默认拷贝构造函数,对属性进行值拷贝

    4. 赋值运算符 operator=, 对属性进行值拷贝

    如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

    示例:

    1.  class Person
    2.  {
    3.  public:
    4.  ​
    5.   Person(int age)
    6.   {
    7.   //将年龄数据开辟到堆区
    8.   m_Age = new int(age);
    9.   }
    10.  ​
    11.   //重载赋值运算符
    12.   Person& operator=(Person &p)
    13.   {
    14.   if (m_Age != NULL)
    15.   {
    16.   delete m_Age;
    17.   m_Age = NULL;
    18.   }
    19.   //编译器提供的代码是浅拷贝
    20.   //m_Age = p.m_Age;
    21.  ​
    22.   //提供深拷贝 解决浅拷贝的问题
    23.   m_Age = new int(*p.m_Age);
    24.  ​
    25.   //返回自身
    26.   return *this;
    27.   }
    28.  ​
    29.  ​
    30.   ~Person()
    31.   {
    32.   if (m_Age != NULL)
    33.   {
    34.   delete m_Age;
    35.   m_Age = NULL;
    36.   }
    37.   }
    38.  ​
    39.   //年龄的指针
    40.   int *m_Age;
    41.  ​
    42.  };
    43.  ​
    44.  ​
    45.  void test01()
    46.  {
    47.   Person p1(18);
    48.  ​
    49.   Person p2(20);
    50.  ​
    51.   Person p3(30);
    52.  ​
    53.   p3 = p2 = p1; //赋值操作
    54.  ​
    55.   cout << "p1的年龄为:" << *p1.m_Age << endl;
    56.  ​
    57.   cout << "p2的年龄为:" << *p2.m_Age << endl;
    58.  ​
    59.   cout << "p3的年龄为:" << *p3.m_Age << endl;
    60.  }
    61.  ​
    62.  int main() {
    63.  ​
    64.   test01();
    65.  ​
    66.   //int a = 10;
    67.   //int b = 20;
    68.   //int c = 30;
    69.  ​
    70.   //c = b = a;
    71.   //cout << "a = " << a << endl;
    72.   //cout << "b = " << b << endl;
    73.   //cout << "c = " << c << endl;
    74.  ​
    75.   system("pause");
    76.  ​
    77.   return 0;
    78.  }

    五、关系运算符重载

    作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

    示例:

    1.  class Person
    2.  {
    3.  public:
    4.   Person(string name, int age)
    5.   {
    6.   this->m_Name = name;
    7.   this->m_Age = age;
    8.   };
    9.  ​
    10.   bool operator==(Person & p)
    11.   {
    12.   if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
    13.   {
    14.   return true;
    15.   }
    16.   else
    17.   {
    18.   return false;
    19.   }
    20.   }
    21.  ​
    22.   bool operator!=(Person & p)
    23.   {
    24.   if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
    25.   {
    26.   return false;
    27.   }
    28.   else
    29.   {
    30.   return true;
    31.   }
    32.   }
    33.  ​
    34.   string m_Name;
    35.   int m_Age;
    36.  };
    37.  ​
    38.  void test01()
    39.  {
    40.   //int a = 0;
    41.   //int b = 0;
    42.  ​
    43.   Person a("孙悟空", 18);
    44.   Person b("孙悟空", 18);
    45.  ​
    46.   if (a == b)
    47.   {
    48.   cout << "a和b相等" << endl;
    49.   }
    50.   else
    51.   {
    52.   cout << "a和b不相等" << endl;
    53.   }
    54.  ​
    55.   if (a != b)
    56.   {
    57.   cout << "a和b不相等" << endl;
    58.   }
    59.   else
    60.   {
    61.   cout << "a和b相等" << endl;
    62.   }
    63.  }
    64.  ​
    65.  ​
    66.  int main() {
    67.  ​
    68.   test01();
    69.  ​
    70.   system("pause");
    71.  ​
    72.   return 0;
    73.  }

    六、函数调用运算符重载

    • 函数调用运算符 () 也可以重载

    • 由于重载后使用的方式非常像函数的调用,因此称为仿函数

    • 仿函数没有固定写法,非常灵活

    示例:

    1.  class MyPrint
    2.  {
    3.  public:
    4.   void operator()(string text)
    5.   {
    6.   cout << text << endl;
    7.   }
    8.  ​
    9.  };
    10.  void test01()
    11.  {
    12.   //重载的()操作符 也称为仿函数
    13.   MyPrint myFunc;
    14.   myFunc("hello world");
    15.  }
    16.  ​
    17.  ​
    18.  class MyAdd
    19.  {
    20.  public:
    21.   int operator()(int v1, int v2)
    22.   {
    23.   return v1 + v2;
    24.   }
    25.  };
    26.  ​
    27.  void test02()
    28.  {
    29.   MyAdd add;
    30.   int ret = add(10, 10);
    31.   cout << "ret = " << ret << endl;
    32.  ​
    33.   //匿名对象调用  
    34.   cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
    35.  }
    36.  ​
    37.  int main() {
    38.  ​
    39.   test01();
    40.   test02();
    41.  ​
    42.   system("pause");
    43.  ​
    44.   return 0;
    45.  }

  • 相关阅读:
    [附源码]SSM计算机毕业设计志愿者管理系统论文2022JAVA
    gcc -static参数
    STM32(十)------- SPI通信
    java计算机毕业设计摄影网上预约管理系统(附源码、数据库)
    java开发环境配置
    力扣647-回文字符串——中心扩展法
    事务的ACID特性
    2022届计算机毕业论文(设计)学生选题参考合集推荐收藏
    组合优于继承:什么情况下可以使用继承?
    Spring Boot中实现发送文本、带附件和HTML邮件
  • 原文地址:https://blog.csdn.net/qq_26126363/article/details/133586201