第30課 操作符過載的概念
函式過載能夠擴充套件系統中已經存在的函式功能,那麼過載是否可以擴充套件其他更多功能
1. 複數類需要解決的問題
——下面的複數解決方案是否可行?
不可行,+操作符只提供對C++ 基本資料型別的運算,不支援類(複數)的相加運算。
+操作符能不能作用類之間--------不能
1 #include<stdio.h> 2 3 //複數解決方案 物件可以進行加法操作嗎 不足之處:應該講成員影藏 4 class Complex 5 { 6 public: 7 int a; //實部8 int b; //虛部 9 }; 10 11 //全域性函式 引數為複數物件 12 Complex add(const Complex& p1, const Complex& p2) 13 { 14 Complex ret; //定義返回值型別 15 16 ret.a = p1.a + p2.a; 17 ret.b = p1.b + p2.b; 18 19 return ret; 20 } 21 22 int main() 23 { 24 Complex c1 = { 1,2 }; 25 Complex c2 = { 3,4 }; 26 // Complex c3 = c1 + c2; // 物件之間不可以進行加法操作 27 Complex c3 = add(c1,c2); //加法操作換成函式呼叫 28 29 printf("c3.a=%d,c3.b=%d\n", c3.a, c3.b); //4,6 30 31 return 0; 32 }
第一個解決方案
1 #include<stdio.h> 2 3 //複數解決方案 物件可以進行加法操作嗎 4 class Complex 5 { 6 inta; //實部 7 int b; //虛部 8 public: 9 Complex(int a = 0, int b = 0) //建構函式將實部虛部隱藏 10 { 11 this->a = a; 12 this->b = b; 13 } 14 15 int getA() //功能函式 16 { 17 return a; 18 } 19 int getB() //功能函式 20 21 { 22 return b; 23 } 24 25 friend Complex add(const Complex& p1, const Complex& p2); //add函式作為友元函式 26 27 }; 28 29 //全域性函式---------引數為複數物件----不能直接訪問類的成員,所以使用友元 30 Complex add(const Complex& p1, const Complex& p2) 31 { 32 Complex ret; //定義返回值型別 33 34 ret.a = p1.a + p2.a; //呼叫有緣函式解決可以呼叫類的成員 35 ret.b = p1.b + p2.b; 36 37 return ret; 38 } 39 40 int main() 41 { 42 //使用建構函式進行初始化 43 Complex c1 (1,2 ); 44 Complex c2 (3,4 ); 45 Complex c3 = add(c1, c2); //c1+c2比較完美 46 47 printf("c3.a=%d,c3.b=%d\n", c3.getA(), c3.getB()); 48 49 return 0; 50 }
思考:Add 函式可以解決Complex 物件相加的問題,但是 Comples 是現實世界中確實存在的複數,並且複數在數學中的地位和普通的實數相同。
c可以支援整形浮點的+操作符運算,對於複數加法,由於複數類是我們自己定義實現的,那麼可不可以自定義+操作符
為什麼不讓 + 操作符也支援複數相加呢?
2.操作符過載
(1)C++中的過載能夠擴充套件操作符的功能
(2)操作符的過載以函式的方式進行,
(3)本質:
是用特殊形式的函式擴充套件操作符的功能
(3)通過operator關鍵字可以定義特殊函式,operator的本質是通過函式來過載操作符
(4)語法:TypeoperatorSign(const Type p1, const Type p2)
{
Type ret;
return ret;
}
Sign為系統中預定義操作符,如+、-、*、/,等
1 #include<stdio.h> 2 3 //複數解決方案 讓+操作支援繼續複數 4 /* 5 operator 關鍵字 定義特殊函式 聽過函式過載操作符 6 */ 7 8 9 class Complex 10 { 11 int a; //實部 12 int b; //虛部 13 public: 14 Complex(int a = 0, int b = 0) 15 { 16 this->a = a; 17 this->b = b; 18 } 19 20 int getA() 21 { 22 return a; 23 } 24 int getB() 25 26 { 27 return b; 28 } 29 30 //方式一:通過全域性普通的函式實現複數相加 31 friend Complex Add(const Complex& p1, const Complex& p2); 32 33 34 //方式二:通過全域性函式過載“+”操作符實現複數相加 35 friend Complex operator + (const Complex& p1, const Complex& p2); 36 37 }; 38 39 //全域性普通函式 40 Complex Add(const Complex& p1, const Complex& p2) 41 { 42 Complex ret; 43 44 ret.a = p1.a + p2.a; 45 ret.b = p1.b + p2.b; 46 47 return ret; 48 } 49 50 //Complex add(const Complex& p1, const Complex& p2) 51 52 //add全部換為operator + 53 54 //全域性過載操作符+ 55 Complex operator + (const Complex& p1, const Complex& p2) 56 { 57 Complex ret; 58 59 ret.a = p1.a + p2.a; 60 ret.b = p1.b + p2.b; 61 62 return ret; 63 } 64 65 int main() 66 { 67 68 Complex c1(1, 2); 69 Complex c2(3, 4); 70 71 //方式一的呼叫 72 //Complex c3 = Add(c1, c2); //方式一呼叫。缺點是無法寫成:c1 + c2的形式; 73 74 //方式二的呼叫 75 //Complex c3 = operator+(c1, c2);//把“opertor+”當成函式名一樣的呼叫 76 77 Complex c3 = c1 + c2; //更直觀,本質上是呼叫“operator+”這個函式 78 79 printf("c3.a=%d,c3.b=%d\n", c3.getA(), c3.getB()); 80 81 return 0; 82 }
3.可將操作符過載函式定義為類的成員函式
(1)比全域性操作符過載函式少一個引數(左運算元this引數充當)------借用成員函式隱含this指標
(2)不需要依賴友元就可以完成操作符過載
(3)編譯器優先在成員函式中尋找操作符過載函式
1 #include<stdio.h> //不依賴友元完成操作符過載 儘量不使用友元 用類的成員函式擴充套件 2 3 class Complex 4 { 5 int a; 6 int b; 7 public: 8 Complex(int a = 0, int b = 0) 9 { 10 this->a = a; 11 this->b = b; 12 } 13 14 int getA() 15 { 16 return a; 17 } 18 int getB() 19 20 { 21 return b; 22 } 23 24 //優先呼叫成員函式版本 25 Complex operator + (const Complex& p) //操作符過載函式 26 { 27 Complex ret; 28 printf("Complex operator + (const Complex& p) \n"); 29 30 ret.a = this->a + p.a; //左運算元this+ 右運算元 31 ret.b = this->b + p.b; 32 33 return ret; 34 } 35 36 friend Complex operator +(const Complex& p1, const Complex& p2); //add函式作為友元函式 37 38 }; 39 40 //全域性函式過載版本 41 Complex operator + (const Complex& p1, const Complex& p2) 42 { 43 Complex ret; //定義返回值型別 44 printf("Complex operator + (const Complex& p1, const Complex& p2)\n"); 45 46 ret.a = p1.a + p2.a; 47 ret.b = p1.b + p2.b; 48 49 return ret; 50 } 51 52 53 54 int main() 55 { 56 57 //使用建構函式進行初始化 58 Complex c1(1, 2); 59 Complex c2(3, 4); 60 Complex c3 = c1.operator + (c2); // Complex c3 = operator + (c1, c2); 61 Complex c3 = c1 + c2; //優先選擇成員函式,而不是全域性的operator+ 62 63 64 printf("c3.a=%d,c3.b=%d\n", c3.getA(), c3.getB()); 65 66 return 0; 67 }
4.小結
(1)操作符過載是C++的強大特性之一,其本質是通過函式擴充套件操作符的功能
(2)operator關鍵字是實現操作符過載的關鍵
(3)操作符過載遵循相同的函式過載規則
(4)全域性函式和成員函式都可以實現對操作符的過載,但編譯器優先選擇通過成員函式實現的操作符過載函式