对于内置的数据类型,编译器知道如何运算。但是对于自定义数据类型,编译器不知道怎么运算。因此,才衍生出了运算符重载。

1、加号运算符重载;

  一种方式通过成员函数重载,另一种通过全局函数重载。

 1 class Person{
 2 public:
 3     //通过成员函数重载+
 4     /*Person operator+(Person &p){
 5         Person temp;
 6         temp.m_A = this->m_A + p.m_A;
 7         temp.m_B = this->m_B + p.m_B;
 8         return temp;
 9     }*/
10     int m_A;
11     int m_B;
12 };
13 //通过全局函数重载加号
14 Person operator+(Person &p1, Person &p2){
15     Person temp;
16     temp.m_A = p1.m_A + p2.m_A;
17     temp.m_B = p1.m_B + p2.m_B;
18     return temp;
19 }
20 Person operator+(Person &p1, int i){
21     Person temp;
22     temp.m_A = p1.m_A + i;
23     temp.m_B = p1.m_B + i;
24     return temp;
25 
26 }
27 void test01(){
28     Person p1;
29     p1.m_A = 10;
30     p1.m_B = 10;
31     Person p2;
32     p2.m_A = 10;
33     p2.m_B = 10;
34     Person p3;
35     p3 = p1 + p2;
36     Person p4;
37     //p4 = p1 + 10; 简化
38     p4 = operator+(p1, 100);
39     cout << p3.m_A <<" "<< p3.m_B << endl;
40     cout << p4.m_A << " " << p4.m_B << endl;
41 }

2、左移运算符重载

  如果想直接输出自定义对象,只能用全局函数重载左移运算符,用成员函数重载左移运算符不能实现cout在左边。

 1 #include<iostream>
 2 using namespace std;
 3 class Person{
 4     friend ostream & operator<<(ostream &cout, Person &p);
 5 public:
 6     Person(int a,int b){
 7         m_A = a;
 8         m_B = b;
 9     }
10 private:
11     
12     int m_A;
13     int m_B;
14 };
15 ostream & operator<<(ostream &cout,Person &p){
16     cout << p.m_A <<"  " << p.m_B ;
17     return cout;
18 }
19 void test01(){
20     Person p1(10,20);
21     cout << p1 << endl; //链式编程思想
22 }
23 int main(){
24     test01();
25     system("pause");
26 }

3、递增运算符重载

 1 #include<iostream>
 2 using namespace std;
 3 class MyInteger{
 4     friend ostream & operator<<(ostream &out, MyInteger &p);
 5 public:
 6     MyInteger(){
 7         m_Int = 0;
 8     }
 9     //重载前置++运算符
10     MyInteger & operator++(){
11         m_Int++;
12         return *this;
13     }
14     //重载后置++运算符
15     MyInteger operator++(int){//int表示占位参数,可以用于区分前置和后置
16         //先记录
17         MyInteger temp = *this;
18         //递增
19         m_Int++;
20         //返回记录
21         return temp;
22     }
23 
24 private:
25     int m_Int;
26 };
27 //重载左移运算符
28 ostream & operator<<(ostream &out, MyInteger &p){
29     cout << p.m_Int;
30     return out;
31 }
32 void test01(){
33     MyInteger myint;
34     cout << ++(++myint) << endl;
35     cout << myint << endl;
36 }
37 void test02(){
38     MyInteger p1;
39     cout << p1++ << endl;
40     cout << p1 << endl;
41 }
42 int main(){
43     /*test01();*/
44     test02();
45     system("pause");
46 }

  后置++,返回值不能是引用,因为temp是一个局部变量,当函数执行完毕temp被释放,再对temp进行操作就是非法的。

4、赋值运算符重载。

  编译器会给一个类至少添加四个函数:

  a.默认的构造函数;(空实现)

  b.默认析构函数;(空实现)

  c.默认拷贝构造函数;(简单值拷贝)

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

 1 #include<iostream>
 2 using namespace std;
 3 class Person{
 4 public:
 5     Person(int age){
 6         m_Age=new int(age);//堆区手动释放
 7     }
 8     
 9     ~Person(){
10         if (m_Age!=NULL)
11         {
12             delete m_Age;
13             m_Age = NULL;
14         }
15     }
16     //重载赋值运算符
17     Person & operator = (const Person &p){
18         //先把堆区的属性释放干净,然后再深拷贝
19         if (m_Age!=NULL)
20         {
21             delete m_Age;
22             m_Age = NULL;
23         }
24         //编译器提供 m_Age = p.m_Age;
25         m_Age = new int(*p.m_Age);//深拷贝
26         return *this;
27     }
28     int *m_Age;
29 };
30 void test01(){
31     Person p1(18);
32     Person p2(20);
33     Person p3(1);
34     p3=p1 = p2;//赋值  会重复释放
35     cout << *p2.m_Age << endl;
36     cout << *p3.m_Age << endl;
37 
38 }
39 int main(){
40     test01();
41     system("pause");
42 }

  以上重载赋值运算符严格来说是有问题的,假设一个特殊情况,p1=p1,自我赋值,如果一上来就执行第19行代码,m_Age所指的空间已经释放了,后面如何进行深拷贝?

 修改后的写法

Person &operator=(const Person&p)
{
   if(&p==this)    //自我赋值检查
    {
        return *this;  
    }  
   delete m_Age;
   m_Age=new int(*p.m_Age);
  return *this;
}

 

5、关系运算符重载

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Person {
 5 public:
 6     Person(string name,int age){
 7         m_name = name;
 8         m_Age = age;
 9     }
10     bool operator==(Person &p){
11         if (this->m_Age == p.m_Age && this->m_name == p.m_name)
12         {
13             return true;
14         }
15         else
16         {
17             return false;
18         }
19     }
20     bool operator!=(Person &p){
21         if (this->m_Age != p.m_Age || this->m_name != p.m_name){
22             return true;
23         }
24         else
25         {
26             return false;
27         }
28     }
29     string m_name;
30     int m_Age;
31 };
32 void test01(){
33     Person p1("tom", 18);
34     Person p2("tom", 18);
35     if (p1==p2)
36     {
37         cout << "p1和p2相等" << endl;
38     }
39     else if (p1!=p2)
40     {
41         cout << "不相等" << endl;
42     }
43 
44 }
45 int main(){
46     test01();
47     system("pause");
48 }

6、重载小括号

  又称仿函数。

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Myprint{
 5 public:
 6     void operator()(string test)
 7     {
 8         cout << test << endl;
 9     }
10 };
11 int main()
12 {
13     Myprint print;
14     print("hello world");
15     system("pause");
16 }