知識梳理 運算子過載

2021-10-08 11:57:06 字數 3813 閱讀 4922

運算子過載的需求

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

double n=

2+c;

//等價於double n=2+c.operator double(), +未被過載,c自動被轉換成double型別

cout

自增自減運算子發過載

自增自減運算子++/–都有前置和後置之分,為了區分所過載的是前置運算子還是後置運算子,規定:

前置運算子作為一元運算子過載(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 ...