【C++】运算符重载

avatar
作者
筋斗云
阅读量:0

目录

一、示例

二、operator

三、加减号重载

四、左移运算符重载 ( << )

五、递增运算符重载(++)

六、赋值运算符重载 (=)

七、关系运算符重载(> < = !=)

八、函数调用运算符重载

查漏补缺:


一、示例

如果我想实现以下代码,按照下面的写法是不能正常运行的。

class Person { public:      int m_A;     int m_B; };  Person p1; p1.m_A = 10; p1.m_B = 10;  Person p2; p2.m_A = 10; p2.m_B = 10;  Person p3; p3 = p1 + p2;

按照以上学过的内容,可以自己写成员函数,实现两个对象相加属性后返回新对象

Person add(Person &p) {     Person temp;     temp.m_A = this -> m_A + p.m_A;     temp.m_B = this -> m_B + p.m_B;     return temp; //返回值会创建一个新的对象出来 }
二、operator

编译器起一个通用重载的名称:operator

对已有运算符重新定义,赋予另一种功能,适应不同的数据类型

注意:

①对于内置的数据类型的表达式的运算符是不可能改变的:int、float、double

②不要滥用运算符重载:把加法写成减法...

三、加减号重载

* 通过成员函数重载 + 号运算符

class Person { public:          Person operator+(Person &p)     {         Person temp;         temp.m_A = this -> m_A + p.m_A;         temp.m_B = this -> m_B + p.m_B;         return temp; //返回值会创建一个新的对象出来     }      int m_A;     int m_B;      };  void test() {     Person p1;     p1.m_A = 10;     p1.m_B = 10;      Person p2;     p2.m_A = 10;     p2.m_B = 10;          //原理:Person p3 = p1.operator+(p2);     //简化如下:     Person p3 = p1 + p2; }

* 通过全局函数重载 + 号运算符

class Person { public:      int m_A;     int m_B;      };  Person operator+ (Peerson &p1, Person &p2) {     Person temp;     temp.m_A = p1.m_A + p2.m_A;     temp.m_B = p1.m_B + p2.m_B;     return temp; }  void test() {     Person p1;     p1.m_A = 10;     p1.m_B = 10;      Person p2;     p2.m_A = 10;     p2.m_B = 10;          //原理:Person p3 = operator+ (p1,p2);     //简化如下:     Person p3 = p1 + p2; }

* 运算符函数重载

class Person { public:      int m_A;     int m_B;      };  Person operator+ (Peerson &p1, int num) {     Person temp;     temp.m_A = p1.m_A + num;     temp.m_B = p1.m_B + num;     return temp; }  void test() {     Person p1;     p1.m_A = 10;     p1.m_B = 10;      //原理:Person p3 = operator+ (p1,num);     //简化如下:person + int     Person p3 = p1 + 10 ; }
四、左移运算符重载 ( << )

* 使得cout可以输出person类数据

class Person {     friend ostream & operator<<(ostream &cout,Person p);  public:     Person(int a, int b)     {         m_A = a;         m_B = b;     }  private:      //利用成员函数来重写左移运算符     //如果不知道该函数应该返回什么 可以先写一个void做测试     //通常不会使用成员函数重载<<运算符,因为无法实现 cout在左侧 会出现 p << cout 的简化方式     //void operator<<( cout )     //{}          int m_A;     int m_B; };  //只能利用全局函数重载左移运算符 //不清楚cout是什么类型,可以右键跳转定义 //ostream标准输出流对象,因为全局只有一个,所以需要用引用方式传过来 ostream & operator<<(ostream &cout,Person p) //本质:operator<< (cout,p) 简化形式:cout << p {     cout << "m_A = " << p.m_A << " m_B = " << p.m_B;     return cout; }  void test() {     Person p(10,10);      //调用完返回cout就可以链式编程不断追加     cout << p << endl; }
五、递增运算符重载(++)

可以利用该方法写一个int数据类型

** 注意前置递增和后置递增的返回类型区别

class MyInt {      friend ostream& operator<<(ostream& cout,MyInt mint);  public:     MyInt()     {         m_Num = 0;     }      //成员函数重载前置++运算符     //返回引用不返回值,为了一直对一个数据进行递增操作,而非对一个新的数据进行操作     MyInt& operator++()     {         //先进行++运算         m_Num++;         //再将自身作为返回         return *this; //this指向自身,*将其解引用     }      //成员函数重载后置++运算符     //int代表的是占位参数,用于区分前置和后置递增,只能写int其他不行     //后置需要返回值,不能返回应用,因为temp是局部对象,返回引用是非法操作     MyInt operator++(int)     {         //先返回结果(记录当时结果)         MyInt temp = *this;         //再进行递增         m_Num++;         //最后将结果返回         return temp;     }  private:     int m_Num;  };  ostream& operator<<(ostream& cout,MyInt mint) {     cout << mint.m_Num;     return cout; }  void test() {     MyInt mint;     cout << mint << endl; // 0     cout << ++mint << endl; // 1     cout << mint++ << endl; // 1     cout << mint << endl; // 2 }
六、赋值运算符重载 (=)

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

①默认构造函数:无参,函数体为空

②默认析构函数:无参,函数体为空

③默认拷贝构造函数:对属性进行值拷贝

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

class Person { public:      Person(int age)     {         m_Age = new int(age); //将age数据创建在堆区,并使用指针维护该数据     }      //堆区数据由程序员手动创建及释放     ~Person()     {         if(m_Age != NULL)         {             delete m_Age;             m_Age = NULL;         }     }      int *m_Age; };  void test() {     Person p1(18);     Person p2(20);      //该方法为浅拷贝 会出现p1p2重复释放 程序崩溃     p2 = p1;     //利用深拷贝解决该问题      cout << "p1的年龄为:" << *p1.m_Age << endl;      cout << "p2的年龄为:" << *p2.m_Age << endl; }

** 重载赋值运算符

class Person { public:      Person(int age)     {         m_Age = new int(age); //将age数据创建在堆区,并使用指针维护该数据     }      //重载赋值运算符     Person& operator=(Person &p)     {         //编译器提供的是浅拷贝:m_Age = p.m_Age; 不可取         //先判断是否有属性在堆区,如果有需要先释放干净,再深拷贝         if(m_Age != NULL)         {             dekete m_Age;             m_Age = NULL;         }          m_Age = new(*p.m_Age);         return *this;     }       //堆区数据由程序员手动创建及释放     ~Person()     {         if(m_Age != NULL)         {             delete m_Age;             m_Age = NULL;         }     }      int *m_Age; };  void test() {     Person p1(18);     Person p2(20);     Person p3(30);         cout << "p1的年龄为:" << *p1.m_Age << endl;      cout << "p2的年龄为:" << *p2.m_Age << endl;      cout << "p3的年龄为:" << *p3.m_Age << endl; }
七、关系运算符重载(> < = !=)

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

class Person { public:      Person(string name, int age)     {         this->m_Name = name;         this->m_Age = age;     };      //重载关系运算符==号     bool operator==(Person &p)     {         if(this->m_Name == p.m_Name && this->m_Age == p.Age)         {             return true;         }             return false;     }      //重载关系运算符!=号     bool operator==(Person &p)     {         if(this->m_Name == p.m_Name && this->m_Age == p.Age)         {             return false;         }             return true;     }      string m_Name;     int m_Age;      };  void test() {     Person p1("Tom", 18);     Person p2("Tom", 18);      if(p1 == p2)     {         cout << "p1和p2是相等的" << endl;     }     else     {         cout << "p1和p2是不相等的" << endl;     }      }
八、函数调用运算符重载

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

②由于重载后使用的方法像函数的调用,故称为仿函数

③仿函数没有固定写法

class MyPrint { public:      void operator()(string text)     {         cout << text << endl;     }  };  void test01() {     //重载()操作符,仿函数     MyPrint myFunc;     myFunc(“hello!”); }  class MyAdd { public:      int operator()(int num1, int num2)     {        return num1 + num2;     } };  void test02() {     MyAdd myadd;     int ret = myadd(1,2);     cout << "ret=" << ret << endl;      //匿名函数对象     cout << MyAdd()(100, 100) << endl; }

查漏补缺:

函数重载和函数重写的区别:https://blog.csdn.net/inter_peng/article/details/53940179

递增运算符复习:

int a = 10; cout << ++a << endl; // 11 cout << a << endl; //11  int b = 10; cout << b++ << endl; //10 cout << b << endl; //11

new关键字使用方法:https://blog.csdn.net/qq_15345177/article/details/88066050

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!