C Primer第五版筆記 過載運算子(一)

2021-08-22 13:25:10 字數 2939 閱讀 9298

過載運算子是具有特殊名字的函式:由關鍵字operator加上要定義的運算符號組成,與其它函式相同,也有返回值、引數列表以及函式體。

當乙個運算子函式是類的成員函式時,this指標繫結到左側運算物件。

我能只能過載已有的大多數運算子,而無權發明新的運算符號:

通常情況下也不過載逗號、取位址、邏輯與、邏輯或運算子。

輸入、輸出運算子:

io標準庫使用》和《來執行輸入和輸出操作,io庫定義了內建型別的版本,而類則需要自定義設和其物件的版本以支援io操作。

輸出運算子<

通常情況下,輸出運算子的第乙個形參是乙個非常量ostream物件的引用:之所以是非常量的是因為向流寫入內容會改變其狀態;是引用是因為我們無法直接複製乙個ostream的物件。

第二個形參一般是乙個常量的引用,該變數是要列印的類型別:是引用的原因是希望避免複製實參;是常量的原因是不應該改變列印物件的內容。

為了與其他輸出運算子一致,該函式一般返回它的ostream形參,例如:

ostream& operator<
輸出運算子應該是控制輸出的內容,而不是輸出的格式,所以不應該在函式中列印換行符。

輸入運算子》:

通常情況下,輸入運算子的第乙個形參是運算子將要讀取的流的引用,第二個形參是將要讀入到的物件的引用,返回值通常會返回某個給定流的引用。第二個形參之所以必須是非常量是因為需要改變他的狀態。例如:

istream& operator>>(istream& is,a& item)

else

return is;

}

輸入運算子必須處理可能失敗的情況,而輸出運算子不需要。

輸入時的錯誤:

在執行輸入運算子時可能發生以下錯誤:

1.當流含有錯誤型別的資料時讀取操作可能失敗,比如需要讀取數字型別,但是輸入的不是資料型別,則讀取操作和後續對流的其他使用都將失敗;

2.當讀取操作到達檔案末尾或者遇到輸入流的其他錯誤時也會失敗。

算術和關係運算子:

通常將算術運算子和關係運算子定義為非成員的函式以允許對左側或右側的運算物件進行轉換。

相等運算子:

設計準則:

1.應當定義operator==,而非新的函式名;

2.判斷引數是否重複;

3.應該具有傳遞性,即a==b,b==c,則a==c;

4.應有相應的operator!=;

關係運算子:

定義了相等運算子的類也常常包含關係運算子。特別是,因為關聯容器和一些演算法要用到小於運算子,所以定義operator《會很有用。

通常情況下,關係運算子應該:

1.定義順序關係,令其與關聯容器中對關鍵字的要求一致;

2.如果有定義相等運算子,則應該有一種關係表示相等

賦值運算子:

我們可以過載賦值運算子,不論形參的型別是什麼,都必須將其定義為成員函式,

復合賦值運算子(比如+=)通常情況下也應該定義為類的成員,這兩類運算都應該返回左側運算物件的引用。

下標運算子:

表示容器的類通常可以通過元素的位置來訪問元素,這些類通常會定義下標運算子,其必須是成員函式。

下標運算子的返回值通常是所訪問的元素的引用,這樣在呼叫賦值運算子時可以出現在任意一端,進一步,最好同時定義返回普通引用和常引用的下標運算子。

遞增遞減運算子:

c++語言並不要求遞增/遞減運算子必須是類的成員,只是建議這麼做,因為它改變的是操作物件的狀態。一般遞增遞減都有前置和後置版本,自己定義時也應該定義兩個版本。

前置遞增/遞減運算子:

*** operator++();

*** operator–();

在做遞增操作時,應該先有乙個檢查操作,判斷當前的指標是否是指向最後乙個元素;做遞減操作時,應該先遞減,然後在檢查指標是否指向無效的位址。

區分前置和後置:

普通的過載形式無法區分這兩種情況,它們使用的符號,函式名相同,並且運算物件數量和型別也相同。為了區分,後置版本接受乙個(並不會使用)額外的int型別的引數,儘管在語法上後置函式可以使用這個引數,但是在實際情況中一般是不會使用的,它的作用就是為了和前置區分而已。

*** operator++(int);

*** operator–(int);

因為不會使用到int形參,所以不需為其命名,另外在後置的版本中,不需要先檢查是否物件是否有效,因為後置遞增遞減是先返回當前狀態,然後再遞增或遞減。

成員訪問運算子:

迭代器類和智慧型指標類常用到解引用運算子(*)和箭頭運算子(->)。過載時也需要先檢查當前指標是否仍在作用範圍內,如果是,解引用運算子返回當前指標所指物件的乙個引用,箭頭運算子返回該物件的位址。

箭頭運算子必須是類的成員,解引用運算子雖然並不必須是類的成員,但通常也這麼定義;另外獲取元素並不會改變物件的狀態,所以應該將其定義成const成員:

***& operator*() const

**** operator->() const

對箭頭運算子返回值的限定:大多數的運算子在過載時的函式體中內容是不限制的,比如可以讓遞增運算子只做列印工作,但箭頭運算子不同,它永遠不能丟掉訪問成員這個含義,過載箭頭運算子時可以改變從哪個物件中取得成員,但是取得成員這件事不能變。

C Primer第五版筆記 過載運算子(三)

過載 型別轉換與運算子 我們可以通過定義對於類型別的型別轉換,通過定義型別轉換運算子可以做到這點,轉換建構函式和型別轉換運算子共同定義了類型別轉換,這樣的轉化有時也被稱為使用者自定義的型別轉換。型別轉換運算子 型別轉換運算子是類的一種特殊成員函式,它負責將乙個類型別的值轉換成其他型別,一般形式如下 ...

C Primer第五版筆記 關聯容器

一 型別 關聯容器支援高效的關鍵字查詢和訪問,標準庫中兩個主要的關聯容器是map和set。map中的元素是鍵值對關鍵字表示索引。set中每個元素只包含乙個關鍵字,set支援高效的關鍵字查詢。關聯容器根據三個特性可以分為8種 1 set還是map 2 關鍵字是否可以重複,允許重複的容器名字中都包含單詞...

C Primer第五版筆記 動態陣列

allocator類 為了讓new分配乙個物件陣列,需要在型別名後跟方括號,括號中是分配物件的數目,該數目必須是整型,但不必是常量 new t 分配的記憶體並不是得到乙個陣列,而是得到乙個陣列元素型別的指標,因此不能對動態陣列呼叫begin和end 與普通陣列不同的是,普通陣列不能定義長度為0的陣列...