操作符重載
出自 MBA智库百科(https://wiki.mbalib.com/)
目錄 |
操作符重載,電腦學科概念,就是把已經定義的、有一定功能的操作符進行重新定義,來完成更為細緻具體的運算等功能。操作符重載可以將概括性的抽象操作符具體化,便於外部調用而無需知曉內部具體運算過程。
C++有許多內置的數據類型,包括int,char,double等,每一種類型都有許多運算符,例如加,減,乘,除等。當用戶定義了類的對象時,兩個對象之間是不能進行這些操作的,比如hyong類的對象a+b,這樣的語句如果沒有重載+運算符就會出錯。但C++允許用戶把這些運算符添加到自已的類中以方便類對象之間的運算就像內置類型的運算一樣方便,比如對象a+b這樣就很明白更容易懂,當然也可以在類中定義一個對象間相加的函數,比如a.add(b)調用函數add()以實現兩個對象a和b相加,但是這條語句沒有比a+b更容易讓人理解。
(一)概述
要實現操作符重載就要使用操作符重載函數,操作符重載函數用關鍵字operator實現,其形式為:返回類型 operator 操作符 (參數列表){}。操作符重載函數是一個函數,只不過這個函數的函數名為operator再加上後面要重載的操作符而已,比如要重載+號,則:hyong operator +(hyong m){}這就聲明瞭一個返回類型為hyong的操作符函數,其函數名為operator +
(二)不同情況
當操作符重載函數作為類的成員函數時,操作符重載函數的參數會比作為友元或者獨立於類的操作符重載函數少一個參數,因為操作符重載類成員函數把調用該函數的對象作為函數的第一個參數,也就是隱含的this指針指向調用該函數的第一個對象,所以會少一個參數。
(三)調用方式
(1)5.1調用類中的操作符重載函數的方法:當調用類中定義的操作符重載函數時最左邊的對象是調用操作符重載函數的對象。比如在類hyong中重定義的+操作符 hyong operator +(hyong m){},有類hyong的對象m和n則調用操作符重載函數的方法有m+n和m.operator +(n),前一條語句會自動轉換為後面這條語句,且m+n的表達式中最左邊的對象是調用操作符重載函數的對象,而最右邊的那個將被作為參數傳送。也就是說n+m會轉換成n.operator +(m)。要記住當調用類中定義的操作符重載函數時最左邊的對象是調用操作符重載函數的對象。
(2)5.2 調用友元或獨立的操作符重載函數的方法:當調用類的友元操作符重載函數或獨立的操作符函數時語句m+n會轉換為顯示的調用方式,比如有友元或獨立操作符重載函數hyong operator +(hyong a,hyong b){}則當出現m+n時會轉換成語句operator +(m,n)表達式的第一個對象傳給第一個參數,第二個對象傳給第二個參數。
(四)特殊情況
一般來說操作符重載函數一般不要求作為類的成員函數或者是友元函數,一般情況下可以將操作符重載函數作為類的成員函數。但是有一種情況必須要求操作符函數作為類的友元函數或者是獨立的函數,就是一個內置類型和對象相加的情況。比如有語句m+1和1+m第一條可以在類中定義操作符函數的形式為hyong operator +(int i){},語句m+1可以調用這個函數是正確的,但對於1+m就不能調用這個函數了,因為類中的操作符重載函數是最左邊的對象是調用該函數的對象,但1+m最左邊的是一個內置整型類型1,所以不會調用這條語句,對於這種語句就只能把操作符重載函數定義為獨立的函數或類的友元函數即形如hyong operator +(int i,hyong a){}這樣1+m就會轉換成operator +(1,m)這樣就是正確的。當然如果這個操作符重載函數需要訪問類中的私有成員時,就應把該函數定義為類的友元函數,如果不需要訪問類中的私有成員,則可以定義為友元也可以定義為獨立函數。
必須把它作為類成員函數的運算符有:(),[],->;和任何賦值運算符,重載這些運算符時必須把操作符函數聲明為類的成員函數。
(五)重載限制
1.並不是所有的操作符都能被重載。除了. ,.* ,:: ,? : ,sizeof,typeid這幾個運算符不能被重載,其他運算符都能被重載
2.重載不能改變該運算符用於內置類型時的函義,程式員不能改變運算符+用於兩個int型時的含義。
3.運算符函數的參數至少有一個必須是類的對象或者類的對象的引用。這種規定可以防止程式員運用運算符改變內置類型的函義。
4.重載不能改變運算符的優先順序。
5.重載不能改變運算符的結合律。
6.重載不能改變運算符操作數的個數。比如+需要兩個操作數,則重載的+也必須要有兩個操作數。
(六)返回類型
在某些情況下操作符函數必須返回一個對象類型作為返回值,比如有hyong的對象a,b,c則語句a=b+c其中重載的+操作符就必須返回一個hyong類型的一個對象,以便賦給對象a,不然該語句就會出錯。當然你可以在語句中返回一個臨時對象,也可以返回一個對象的引用,或者返回this指針,不過返回臨時對象會浪費記憶體開銷,所以最好返回類對象的一個引用。
(七)參數傳遞
操作符函數可以按值傳遞也可以按引用傳遞,這根據操作符而定,比如對於+運算符既可以把對象按值傳遞給操作符函數也可以按引用傳遞給操作符函數,而且+操作符不會改變原操作數的值,所以應把傳遞類型聲明為const,比如hyong operator +(const hyong &a,const hyong &b){}。但對於要改變其自身值的操作符比如++運算符,就必須傳遞引用,且不能把該引用聲明為const類型,因為如果操作數按值傳遞的話,傳遞給操作數函數的將是一個對象的副本,兩個副本是獨立的,不能改變到原對象的值,所以應按引用傳遞對象,比如hyong operator ++(hyong &a){}。
(八)運算符++
1.註意++有首碼和尾碼之別,首碼形式是變數先加1然後執行表達式,而尾碼形式則是先執行表達式然後再使變數加1,所以在執行尾碼的++運算符時應先返回對象的原始值,然後才對對象加1。
首碼++返回的是左值,即該對象+1之後的引用。尾碼++返回是的右值。類似於{ int tmp = a; a=a+1; return tmp;} 並不是先執行表達式再加1 而是返回+1之前的值。
2.預設的帶有一個參數的++運算符函數是首碼++運算符,要重載尾碼的++運算符必須採用另一種方式實現。
重載尾碼的++運算符時應給函數多增加一個int參數,該int參數不會使用,應忽略他,該參數只是為了讓編譯器區分++運算符的首碼和尾碼形式之間的區別。比如重載尾碼++運算符的友元函數形式為hyong operator ++(hyong &a,int i){}後面的參數int i沒有實際意義,應忽略他。
(九)運算符+
要註意重載二元運算符時如果有形如1+m這種類型的表達式就必須把該操作符函數定義為非類的成員的形式。因為類中的操作符重載函數是最左邊的對象是調用該函數的對象。
(十)運算符=
1.註意重載賦值運算符和[],(),->;運算符必須定義為類的成員函數。
2.註意:如果程式不提供顯示的賦值運算符則系統會提供一個預設的賦值運算符。
3.什麼時候重載賦值運算符:當類中含有指針成員時,一般都要重定義類的賦值運算符。
4.重載賦值運算符時應有處理語句m=m的情況。其中m是某一個類的對象。如果不處理這樣的語句有時會出現問題,具體什麼問題有待調查。可以用this指針來做處理,比如有語句const A & operator(A &j)則可以用if(this==&j) return *this;這樣的語句來處理,即比較當前調用賦值運算符函數的對象的地址和被賦值的對象的地址,如果地直相等說明是同一個對象。
5.重載賦值運算符時應返回一個對象。因為賦值運算符的左邊是一個對象,所以重載賦值運算符應返回一個類的對象,為了避免不必要的開銷,最好是返回一個類的對象的引用。
6.重載賦值運算符時必須是類的成員函數。


