c++中預定義的運算子的操作物件只能是基本資料型別。
但實際上,對於許多使用者自定義型別(例如類),也需要類似的運算操作。
因此可以重定義或過載大部分 c++ 內建的運算子。這樣,您就能使用自定義型別的運算子。
運算子過載是通過建立運算子函式實現的,運算子函式定義了過載的運算子將要進行的操作。運算子函式的定義與其他函式的定義類似,唯一的區別是運算子函式的函式名是由關鍵字operator和其後要過載的運算子符號構成的。
過載的運算子是帶有特殊名稱的函式,函式名是由關鍵字 operator 和其後要過載的運算子符號構成的。與其他函式一樣,過載運算子有乙個返回型別和乙個引數列表。
過載+
運算子,我們可以給+
重新定義其含義。
例如:
// 使用內建的+運算子操作進行int型別的運算
int a = 10;
int b = 20;
int c = a + b; // 結果為30
如果我們使用+
運算子來運算我們的自定義資料型別時,需要過載+
運算子才可以。
舉個例子:有個我們自定義的資料型別person,有height和weight兩個屬性
class person
};
我們定義兩個物件p1和p2;
person p1(10,10); // 將p1的兩個屬性設定為10,10
person p2(20,20); // 將p2的兩個屬性設定為20,20
如果我們想對p1和p2進行height和weight的分別相加的運算通過,我們需要:
int heigt = p1.height + p2.height;
int weight = p1.weight + p2.weight;
當然我們也可以通過過載+
運算子進行運算:
有兩種方式:
// 成員函式過載+
person operator+(person &p)
成員函式過載的本質:
cout << p1.operator+(p2).height << endl;
可以簡寫為:cout << (p1 + p2).height << endl;
// 全域性函式過載+
person operator+(person& q, person& p)
這種只能兩個兩個進行操作,在vs2019以後,過載的+運算子的結果是乙個純右值,不能作為左值進行計算,所以多個類的例項連續相加會報錯。只能兩兩相加。
//在全域性區開闢一段記憶體,不在全域性函式中開闢,防止函式執行完成後系統**
person temp;
// 全域性函式過載+
person& operator+(person& q, person& p)
返回引用,同時注意不要在棧中開闢空間。
這種可以實現鏈式操作。
全域性函式過載的本質:
cout << operator+(p1, p2).height << endl;
可以簡寫為:cout << (p1 + p2).height << endl;
// 輸出驗證一下
cout << (p1 + p2).height << endl;
cout << (p1 + p2).weight << endl;
如果有兩個以上的物件進行操作:鏈式操作
person p1(10, 10); // 將p1的兩個屬性設定為10,10
person p2(20, 20); // 將p2的兩個屬性設定為20,20
person p3(30, 30); // 將p3的兩個屬性設定為30,30
person p4(40, 40); // 將p3的兩個屬性設定為40,40
person p5(50, 50); // 將p3的兩個屬性設定為50,50
// 輸出驗證一下
cout << (p1 + p2 + p3 + p4 + p5).height << endl; //輸出 150(10+20+30+40+50)
cout << (p1 + p2 + p3 + p4 + p5).weight << endl; //輸出 150(10+20+30+40+50)
由此可見,適當的使用運算子過載可以使程式更加簡潔,方便程式設計。
-
運算子的過載與+
類似,可以根據自己的需要進行程式設計。
作用:可以輸出自定義型別資料
還是以上乙個**為例子
過載<<
同樣有兩種方法:成員函式和全域性函式。分別寫一下:
成員函式過載:
要弄清成員函式過載的本質,即為物件呼叫成員函式,物件.函式名(引數);
比如我們想過載左移運算子用來格式化輸出 物件的 height 和 weight
一開始可以這樣寫:
// 成員函式過載左移運算子
void operator<<(ostream& cout)
呼叫時:
p1.operator<<(cout); // 本質呼叫
p1 << cout; // 簡化之後
這顯然不符合我們的使用習慣。所以要用第二種方法:全域性函式過載。
全域性函式過載
// 將全域性函式宣告為友元函式,可以訪問類中的私有成員
friend void operator<<(ostream& cout, person& p);
// 全域性函式過載左移運算子
void operator<<(ostream& cout, person& p)
呼叫時:
operator<<(cout, p1); // 本質呼叫
cout << p1; // 簡化之後
用這兩種方法,我們成功的將左移運算子過載,使其有了我們想要的功能。
但發現,如果我們想進行鏈式操作,程式會報錯。究其原因,是因為我們的返回型別為void
,進行鏈式操作時,兩種型別不一致,所以無法進行操作。稍作修改,將返回型別改為cout
的返回型別就可以,也就是ostream
。
全域性函式過載左移<<
運算子:
在類中將全域性函式宣告為友元函式
friend ostream& operator<<(ostream& cout, person& p);
// 全域性函式過載左移運算子
ostream& operator<<(ostream& cout, person& p)
這樣一來,我們便可以實現鏈式操作了。
在運算子過載時,實現鏈式操作的關鍵就是注意返回型別,要根據實際情況來看,過載函式的返回值要跟後面進行操作的物件為同一型別,具體情況具體分析。
同樣是兩種方法。以>
為例。
成員函式過載
// 成員函式過載
bool operator>(person& p)
呼叫時:
bool result1 = p2.operator>(p1); // 本質
bool result2 = p1 > p2; // 簡化
cout << result1 << endl;
cout << result2 << endl;
全域性函式過載
friend bool operator>(person& p1, person& p2); // 將全域性函式宣告為友元函式
// 全域性函式過載
bool operator>(person& p1, person& p2)
呼叫時:
bool result1 = p1 > p2; // 簡化
bool result2 = operator>(p1,p2); // 本質
cout << result1 << endl;
cout << result2 << endl;
關於運算子的過載就先寫到這裡,最重要的是了解本質,就是用成員函式或者是全域性函式重新定義一下該運算子的功能,然後去呼叫成員函式或者是全域性函式。
目前就先寫這麼多吧,其他幾種運算子的過載應該是大同小異,有機會的話會更加深入的學習一番。
C 運算子過載 過載特殊運算子
賦值運算子用於同類物件間的相互賦值。賦值運算子只能被過載為類的非靜態成員函式,不能過載為友元函式和普通函式。對於使用者自定義的類而言,如果沒有過載賦值運算子,那麼c 編譯器會為該類提供乙個預設的過載賦值運算子成員函式。預設賦值運算子的工作方式是按位對拷,將等到右邊物件的非靜態成員拷貝給等號左邊的物件...
C 運算子過載賦值運算子
自定義類的賦值運算子過載函式的作用與內建賦值運算子的作用類似,但是要要注意的是,它與拷貝建構函式與析構函式一樣,要注意深拷貝淺拷貝的問題,在沒有深拷貝淺拷貝的情況下,如果沒有指定預設的賦值運算子過載函式,那麼系統將會自動提供乙個賦值運算子過載函式。賦值運算子過載函式的定義與其它運算子過載函式的定義是...
C 運算子過載轉換運算子
為什麼需要轉換運算子?大家知道對於內建型別的資料我們可以通過強制轉換符的使用來轉換資料,例如 int 2.1f 自定義類也是型別,那麼自定義類的物件在很多情況下也需要支援此操作,c 提供了轉換運算子過載函式 它使得自定義類物件的強轉換成為可能。轉換運算子的生命方式比較特別,方法如下 operator...