首页 > 编程语言 >类和对象——C++运算符重载

类和对象——C++运算符重载

时间:2022-11-13 14:13:14浏览次数:51  
标签:p2 p1 C++ 运算符 Person 重载 mAge

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

重载的两类方法:

1.类成员函数重载

2.全局函数重载

注意:运算符重载也可以实现函数重载

引入:

我们希望编译器这样运行:

p3.m_A = p1.m_A + p2.m_A

p3.m_B = p1.m_B + p2.m_B

编译器:?(它看不懂咱们想干什么,并且大为震惊)

为此,我们打算自己写一个类成员函数去实现它(成员函数重载)。

但是编译器受不了,给了我们一个通用名,当我们采用他的通用名时候,就可以实现运算符重载,以简化代码。。

(此处通过成员函数重载了+号)

当然你也可以通过全局函数去实现(全局函数重载):


 1.加减乘除运算符重载:

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

例子(包含函数重载)(只举加号,其余三号相同):

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class Person{
 6 public:
 7 
 8     //1.成员函数重载+号
 9     // Person operator+(Person &p){
10     //     Person temp;
11     //     temp.mA = this->mA + p.mA;
12     //     temp.mB = this->mB + p.mB;
13     //     return temp;
14     // }
15 
16     int mA;
17     int mB;
18 };
19 
20 //2.全局函数重载+号
21 Person operator+(Person &p1, Person &p2){
22     Person temp;
23     temp.mA = p1.mA + p2.mA;
24     temp.mB = p1.mB + p2.mB;
25     return temp;
26 }
27 //函数重载:
28 Person operator+(Person &p1, int num){
29     Person temp;
30     temp.mA = p1.mA + num;
31     temp.mB = p1.mB + num;
32     return temp;
33 }
34 
35 void test01(){
36     Person p1;
37     p1.mA = 10;
38     p1.mB = 10;
39     Person p2;
40     p2.mA = 10;
41     p2.mB = 10;
42     //成员函数重载的本质:Person p3 = p1.operator+(p2);
43     //全局函数重载的本质:Person p3 = operator+(p1,p2);
44     Person p3 = p1 + p2;  //运算符重载
45 
46     Person p4 = p1 + 20;    //函数重载
47     cout << "p3.mA = " << p3.mA << endl;
48     cout << "p3.mB = " << p3.mB << endl;
49 
50     cout << "p4.mA = " << p4.mA << endl;
51     cout << "p4.mB = " << p4.mB << endl;
52 }
53 
54 int main(){
55     test01();
56     system("pause");
57     return 0;
58 }

2.左移运算符(<<)重载(左移运算符通常不采用成员函数重载):

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

设想:

输出p的时候,把p的两个属性也一起输出。

例子:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class Person{
 6     friend ostream & operator<<(ostream &cout,Person p);
 7     friend void test01();
 8 private:
 9     //成员函数重载左移运算符通常不采用,因为无法实现cout在左侧
10     //void operator<<(cout) ==>p.operator<<(cout)
11 
12     int A;
13     int B;
14 };
15 
16 //本质:operator<<(cout ,p)简化为cout << p;
17 //缺少ostream &的话,cout << p后无法再使用链式编程(像是cout << p << "hi" << endl; 这类输出就会报错)
18 ostream & operator<<(ostream &cout,Person p){ //ostream标准输出流类型
19     cout << "A = " << p.A << " B = " << p.B;
20     return cout;
21 }
22 
23 void test01(){
24     Person p;
25     p.A = 10;
26     p.B = 20;
27     cout << p << endl;
28 }
29 
30 int main(){
31     test01();
32     system("pause");
33     return 0;
34 }

3.递增/减运算符重载:

设想:

 

希望对象成为一个整型,可以直接输出

例子1(用左移运算符实现):

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class MyInteger{
 6     friend ostream& operator<<(ostream &cout, MyInteger myint);
 7 private:
 8     int Num;
 9 public:
10     MyInteger(){
11         Num = 0;
12     }
13 };
14 
15 //重载左移运算符
16 ostream& operator<<(ostream &cout, MyInteger myint){
17     cout << myint.Num;
18     return cout;
19 }
20 
21 void test01(){
22     MyInteger myint;
23     cout << myint << endl;
24 }
25 
26 int main(){
27     test01();
28     system("pause");
29     return 0;
30 }

例子2(把myint直接变为整型->即能实现自增或者自减)

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class MyInteger{
 6     friend ostream& operator<<(ostream &cout, MyInteger myint);
 7 private:
 8     int Num;
 9 public:
10     MyInteger(){
11         Num = 0;
12     }
13     //重载前置++运算符,前置重载返回引用
14     MyInteger& operator++(){    //MyInteger&是引用,返回引用是为了一直对一个数据进行操作
15         Num++;
16         return *this;
17     }
18     //重载后置++运算符,后置重载返回值
19     //void operator++(int)  int代表占位参数,用于区分前置和后置递增
20     MyInteger operator++(int){
21         MyInteger temp = *this;
22         Num++;
23         return temp;
24     }
25 };
26 
27 //重载左移运算符
28 ostream& operator<<(ostream &cout, MyInteger myint){
29     cout << myint.Num;
30     return cout;
31 }
32 
33 void test01(){
34     MyInteger myint;
35     cout << myint << endl;
36     cout << ++myint << endl;
37 }
38 void test02(){
39     MyInteger myint;
40     cout << myint << endl;
41     cout << myint++ << endl;
42     cout << myint++ << endl;
43     cout << myint << endl;
44 }
45 
46 int main(){
47     test01();
48     test02();
49     system("pause");
50     return 0;
51 }

4.赋值运算符重载

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

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

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

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

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

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

例子:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class Person{
 6 public:
 7     Person(int age){
 8         mAge = new int(age);
 9     }
10     ~Person(){
11         if(mAge != NULL){
12             delete mAge;
13             mAge = NULL;
14         }
15     }
16     //重载赋值运算符
17     Person& operator=(Person &p){
18         //mAge = p.mAge;   //编译器默认执行的浅拷贝,有堆区存在就会报错
19         if(mAge != NULL){   //检查堆区有没有数据,有就先让他释放干净
20             delete mAge;
21             mAge = NULL;
22         }
23         mAge = new int(*p.mAge);    //深拷贝
24         return *this;
25     }
26     int *mAge;
27 };
28 
29 void test01(){
30     Person p1(10);
31     Person p2(20);
32     Person p3(30);
33     p3 = p2 = p1;    //赋值操作
34     cout << "p1.age = " << *p1.mAge << endl;
35     cout << "p2.age = " << *p2.mAge << endl;
36     cout << "p3.age = " << *p3.mAge << endl;
37 }
38 
39 int main(){
40     test01();
41     system("pause");
42     return 0;
43 }

5.关系运算符重载(==,!=等)

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

想象中:

 

 但是编译器对下面的代码感到疑惑,不知道如何处理。。

因此需要通过重载关系运算符来让编译器明白我们要干什么

例子:

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

6.函数调用运算符重载

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

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

● 没有固定写法,非常灵活

关于第一、二点的例子:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class MyPrint{
 6 public:
 7     //重载函数调用运算符
 8     void operator()(string text){   //伪函数,采用重载函数调用运算符实现
 9         cout << text << endl;
10     }
11 };
12 
13 void MyPrint02(string test){    //真函数
14     cout << test << endl;
15 }
16 
17 void test01(){
18     MyPrint p;
19     p("hello");         //伪函数
20     MyPrint02("hi");    //真函数
21 }
22 
23 int main(){
24     test01();
25     system("pause");
26     return 0;
27 }

关于第三点(利用反函数写一个加法类):

 

 主函数调用test02()即可实现100和100的相加。。

=======================================================

当然我们也可以用匿名函数对象(当前行执行完立即被释放)去实现输出:

 

 与非匿名函数对象进行比较,做好区分!

 

标签:p2,p1,C++,运算符,Person,重载,mAge
From: https://www.cnblogs.com/MorningMaple/p/16880686.html

相关文章