運算子過載的需求
c++預定義的運算子只能用於基本資料型別的運算:整型、實數型、字元型、邏輯性。數學上,兩個複數可以直接進行加減運算,但是c++中用於複數是不被允許的。如何讓物件也能通過運算子進行運算,使得**更加簡介易於理解。
運算子過載就是對已有的運算子賦予多重的含義,使得統一運算子作用於不同型別的資料時導致不同型別的行為。同乙個運算子對不同型別的運算元所發生的行為不同。
運算子過載的形式
運算子過載的實質是函式過載,可以過載為普通函式,也可以過載為成員函式。把含運算子發表示式轉換成對運算子函式的呼叫,把運算子的運算元轉換成運算子函式的引數。運算子被多次過載,根據實參的型別決定呼叫哪乙個運算子函式。過載為成員函式時,引數個數為運算子目數減1,過載為普通函式時,引數個數為運算子目數。
基本樣式:返回值型別 operator 運算子 (形參表)
class
complex
//帶有兩個引數的建構函式
complex operator-(
const complex &c)
;//運算子過載-成員函式};
complex complex::
operator-(
const complex &c)
complex operator+(
const complex &a,
const complex &b)
有時賦值運算子兩邊的型別可能不匹配,如將乙個int型變數賦值給乙個complex物件時,需要過載運算子「=」,賦值運算子「=」只能過載為成員函式。
深拷貝和淺拷貝
如果不定義自己的賦值運算子,那麼s1=s2實際上導致s1.str和s2.str指向同乙個地方,s1原本指向的內容無法得到空間的釋放,造成記憶體的浪費。如果s1物件消亡,析構函式將會釋放s1.str指向的空間,將來s2消亡時還要釋放乙個,不妥當。如果執行s1=other時會導致s2.str指向的地方被delete掉。
string &
operator=(
const string &s)
對operator=的返回值型別的討論
void好不好,string好不好?為什麼是string &?
對運算子過載時,好的風格是盡量保留運算子原本的特性,考慮a=b=c與(a=b)=c的形式,能否連等於賦值?為string類編寫賦值建構函式時,會面臨和=一樣的問題,用同樣的方法處理。
運算子過載為友元函式
一般情況下把運算子過載為類的成員函式是較好的選擇,但是有時過載為成員函式不能滿足使用要求,過載為普通函式又不能訪問類的私有成員,所以將運算子過載為友元。
流插入運算子和流提取運算子的過載
cout是在iostream中定義的ostream類的物件。《能用在cout上是因為在iostream中對《進行了運算子的過載。
如何過載能使得cout對整型和字串型別的變數都可以過載且可以連著寫? 只需將對應的過載函式的返回值的型別改為ostream,即可以接著往下運算接著輸出。即:
cout<<5<<「this」; 等價於 (cout.operator<<(5)).operator<<(「this」);可以加一些其他形式,如改寫成複數的形式,改寫成分數上下表達的形式等。只能過載為全域性變數函式,宣告成對應類的友元。
型別轉換運算子的過載
強制型別轉換如double型、int型。過載函式的返回值型別一般是可以不寫的,因為返回值型別自然就是對應的強制轉換成的型別。就是把類的物件強制轉換成對應型別的形式。可以顯式的轉換,也可以被自動轉換。
class
complex
//建構函式
operator
double()
;//過載強制型別轉換運算子double,將complex物件轉換成double型};
complex c
(1.1
,2.2);
cout<<
(double
)c/強制型別轉換,輸出1.1
double n=
2+c;
//等價於double n=2+c.operator double(), +未被過載,c自動被轉換成double型別
cout/輸出3.1
自增自減運算子發過載
自增自減運算子++/–都有前置和後置之分,為了區分所過載的是前置運算子還是後置運算子,規定:
前置運算子作為一元運算子過載(1
)過載為成員函式,沒有引數:
t&operator++(
) 或 t&
operator--(
)(2)過載為全域性函式,有乙個引數
t1&operator
++(t2) 或 t1&
operator
--(t2)
後置運算子作為二元運算子過載,要多寫乙個沒有用的引數(1
)過載為成員函式,沒有引數
t operator++(
int)或t operator--(
int)(2
)過載為全域性函式,兩個引數
t1 operator
++(t2,
int)或t1 operator
--(t2,
int)
;
class
demo
//建構函式初始化
demo &
operator++(
);demo operator++(
int)
;operator
int();
friend demo &
operator
--(demo &);
friend demo operator
--(demo &
,int);
};demo & demo::
operator++(
)demo demo::
operator++(
int k)
//s++即等價於 s.operator++(0),其中k為0
demo &
operator
--(demo &d)
demp operator
--(demo &d,
int)
//s--等價於operator--(s,0);
demo d(5
);cout<<
(d++);
//等價於d.operator++(0),輸出5,d值為6
cout<<
(++d)
;//等價於d.operator++();輸出7,d值為7
cout<<
(d--);
//等價於operator--(d,0);輸出7,d值為6
cout<<
(--d)
;//等價於operator--(d);輸出5,d值為5
注意
c++不允許定義新的運算子。過載後運算子的含義應該符合日常習慣。運算子過載不改變運算子的優先順序。
. .* :: ?: sizeof 等運算子不能被過載過載(), [ ] ->或賦值運算子=時,必須宣告為類的成員函式
運算子過載知識總結
1.運算子過載 1 過載規則 2 過載運算子的限制 過載運算子函式可以對運算子作出新的解釋,但原有基本語義不變 不改變運算子的優先順序 不改變運算子的結合性 不改變運算子所需要的運算元 不能建立新的運算子 3 運算子函式可以過載為成員函式或友元函式 1 一元運算子 object op或 opobje...
運算子過載之過載型別運算子
普通型別 類型別 呼叫對應的只有乙個引數 引數的型別就是這個普通型別 的建構函式 需求 boy boy1 10000 薪資 建構函式boy int boy boy2 rock 姓名 建構函式boy char 普通型別賦值給類型別其實很簡單,就是專門的對這個賦值的型別定義乙個建構函式。編譯器在執行 的...
運算子過載 賦值運算子的過載
有時候希望賦值運算子兩邊的型別可以不匹配,比如,把乙個int型別變數賦值給乙個complex物件,或把乙個 char 型別的字串賦值給乙個字串物件,此時就需要過載賦值運算子 注意 賦值運算子 只能過載為成員函式 賦值運算子過載例項示例 include include using namespace ...