C 知識 過載運算與型別轉換

2021-09-26 00:15:54 字數 3443 閱讀 3827

最後,如果有理解不對的·地方,希望大家不吝賜教,謝謝!

【c++系列】【前一章:拷貝控制】【下一章:待續】

當運算子作用於類型別的運算物件時,可以通過運算子過載重新定義該運算子的含義。明智地使用運算子過載能令我們的程式更易於編寫和閱讀。

過載的運算子是具有特殊名字的函式:它們的名字由關鍵字operator和其後要定義的運算符號共同組成。和其他函式一樣,過載的運算子也包含返回型別、引數列表以及函式體。

引數數量與該運算子作用的運算物件數量一樣多,一元運算子有乙個引數,二元運算子有兩個。

如果乙個運算子函式是成員函式,則它的第乙個(左側)運算物件繫結到隱式的this指標上,因此,成員運算子函式的(顯式)引數數量比運算子的物件總數少乙個。

對於乙個運算子函式來說,它或者是類的成員,或者至少含有乙個類型別的引數。

//乙個非成員運算子函式的等價呼叫

data1+data2; //普通的表示式

operator+(data1,data2); //等價的函式呼叫

data1+=data2;    //基於「呼叫」的表示式

data1.operator+=(data2); //對成員運算子函式的等價呼叫

某些運算子指定了運算子物件求值的順序,因為使用過載的運算子本質上是一次函式呼叫,所以這些關於運算子求值順序的規則無法應用到過載的運算子上。特別是:邏輯與運算子、邏輯或運算子和逗號運算子(表示式結果是最右邊表示式的結果)的運算物件求值順序規則無法保留下來。

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

io標準庫分別使用》和《執行輸入和輸出操作。

通常情況下,輸出運算子的第乙個形參是乙個非常量ostream物件的引用。 第二個形參一般來說是乙個常量的引用。為了與其他輸出運算子保持一致,operator《一般要返回它的ostream形參。

通常,輸出運算子應該主要負責列印物件的內容而非控制格式,輸出運算子不應該列印換行符。

假設輸入輸出運算子是某個類的成員,則它們也應該必須是istream或ostream的成員。然而,這兩個類術語標準庫,並且我們無法給標準庫中的類新增任何成員。當然,io運算子通常需要讀寫類的非公有資料成員,所以io運算子一般被宣告為友元。

通常情況下,輸入運算子的第乙個形參是運算子將要讀取的流的引用,第二個形參是將要讀入到的(非常量)物件的引用。

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

當讀取操作發生錯誤時,輸入運算子應該負責從錯誤中恢復。

通常情況下,我們把算術和關係運算子定義成非成員函式以允許對左側或右側的運算物件進行轉換,因為這些運算子一般不需要改變物件的狀態,所以形參都是常量引用。

如果類同時定義了算術運算子和相關的復合賦值運算子,則通常情況下應該使用復合賦值來實現算術運算子。

如果存在唯一一種邏輯可靠的《定義,則應該考慮為這個類定義《運算子,如果類同時還包含==,則當且僅當《的定義和==產生的結果一致時才定義《運算子。

和拷貝賦值及移動賦值運算子一樣,其他過載的賦值運算子也必須先釋放當前記憶體空間,再建立一片新空間。

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

復合賦值運算子不非得是類的成員,不過我們還是傾向於把包括復合賦值在內的所有賦值運算都定義在類的內部。返回型別都應該返回左側運算物件的引用。

表示容器的類通常可以通過元素在容器中的位置訪問元素,這些類一般會定義下標運算子operator。下標運算子必須是成員函式。通常以所訪問元素的引用作為返回值,這樣做的好處是下標可以出現在賦值運算子的任意一端。

如果乙個類包含下標運算子,則它通常會定義兩個版本:乙個返回普通引用,另乙個是類的常量成員並且返回常量引用。

定義遞增(++)和遞減(--)運算子的類應該同時定義前置版本和後置版本。這些運算子通常應該被定義成類的成員。

為了與內建版本保持一致,前置運算子應該返回遞增或遞減物件的引用。

為了與內建版本保持一致,後置運算子應該返回物件的原值(遞增或遞減之前的值),返回形式是乙個值而非引用。後置版本接受乙個額外的(不被使用)int型別的形參。當我們使用後置運算子時,編譯器為這個形參提供乙個值為0的實參。 

箭頭運算子不執行任何自己的操作,而是呼叫解引用運算子並返回解引用結果元素的位址。箭頭運算子必須是類的成員,解引用運算子通常也是類的成員,儘管並非必須如此。

過載的箭頭運算子必須返回類的指標或自定義箭頭運算子的某個類的物件。

如果類過載了函式呼叫運算子,則我們可以像使用函式一樣使用該類的物件。因為這樣的類同時也能儲存狀態,所以與普通函式相比它們更加靈活。

函式呼叫運算子必須是成員函式,乙個類可以定義多個不同版本的呼叫運算子,相互之間應該在引數數量或型別上有所區別。

和其他類一樣,函式物件除了operator()之外也可以包含其他成員。函式物件類通常包含一些資料成員,這些資料成員被用於定製呼叫運算子中的操作。

c++語言中有幾種可呼叫的物件:函式、函式指標、lambda表示式、bind建立的物件以及過載了函式呼叫運算子的類。呼叫型別指明了呼叫返回的型別以及傳遞給呼叫的實參型別。一種呼叫型別形式對應乙個函式型別,例如:

int (int,int)  是乙個函式型別,它接受兩個int,返回乙個int

我們可能希望使用這些可呼叫物件構建乙個間單的桌面計算器。為了實現這一目的,需要定義乙個函式表用於儲存指向這些可呼叫物件的「指標」。當程式需要執行某個特定的操作時,從表中查詢該呼叫的函式。

定義在標頭檔案functional中,function是乙個模板,當建立乙個具體的function型別時我們必須提供額外的資訊。

我們不能(直接)將過載函式的名字存入function型別的物件中。解決二義性問題的一條途徑是儲存函式指標,而非函式的名字。同樣,我們也能使用lambda來消除二義性。

轉換建構函式和型別轉換運算子共同定義了類型別轉換,這樣的轉換有時也被稱為使用者定義的型別轉換。

型別轉換運算子是類的一種特殊成員函式,它負責將乙個類型別的值轉換成其他型別。型別轉換函式的一般形式如下所示:

operator type() const;  其中type表示某種型別,型別轉換運算子可以面向任意型別(除了void之外)進行定義,只要該型別能作為函式的返回型別。因此,我們不允許轉換成陣列或者函式型別,但允許轉換成指標(包括陣列指標及函式指標)或者引用型別。

型別轉換運算子既沒有顯式的返回型別,也沒有形參,而且必須定義成類的成員函式,型別轉換運算子通常不應該改變待轉換物件的內容,因此,型別轉換運算子一般被定義成const成員。

乙個型別轉換函式必須是類的成員函式;它不能宣告返回型別,形參列表也必須為空,型別轉換函式通常應該是const。

c 過載運算與型別轉換

1.基礎概念 過載的運算子是具有特殊名字的函式 過載運算子函式,運算子函式。過載運算子 依次包含返回型別,函式名 operator 引數列表,函式體。只有過載的函式呼叫運算子operator 才能有預設實參。關於引數的數量,一般來說,一元運算子有乙個引數,二元有兩個,三元有三個 但是如果該運算子函式...

過載運算與型別轉換

1.基本概念 名字由關鍵字operator和其後要定義的運算符號共同組成。對於乙個運算子來說,它或者是類的成員,或者至少含有乙個類型別的引數。通常情況下,不應該過載逗號 取位址 邏輯與和邏輯或運算子。2.當我們定義過載的運算子時,必須首先決定是將其宣告為類的成員函式還是宣告為乙個普通的非成員函式。一...

C 之過載運算與型別轉換

賦值運算子 算術和關係運算子 下標運算子 遞增和遞減運算子 過載 型別轉換與運算子 過載的運算子是具有特殊名字的函式 它們的名字由關鍵字operator和其後要定義的運算符號共同組成。和其他函式一樣,過載的運算子也包含返回型別 引數列表以及函式體。對於乙個運算子函式來說,它或者是類的成員,或者至少含...