概念:对已有的运算符重新定义,赋予其另一种功能,以适应不同数据类型。。
重载的两类方法:
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