c 學習筆記 類運算子過載與友元與型別轉換

2021-07-04 16:38:13 字數 3660 閱讀 5997

有這樣乙個類:

class str

const char *getstr()const

const int getcount()const

void add(char *pstr)

else

cout << "size error!\n";

} void show()const

~str(){}

};

這個類仿string類(劣質),允許使用者將字串相加(有限制),並且計算字元個數。

但是我們更想用類似內建型別那樣的運算方法:

int a=1,b=3;

a=a+b;

而不是經過物件的方法呼叫來實現:

str s1("hello ");

s1.add("words!");//不想這樣使用

s1.show();//想用cout<

於是,便有了更美觀的方法:運算子過載比如說我們想用下面的方法不是呼叫類方法(add)來進行字串相加:

str s2("c++!");

s1=s1+s2;

這就需要過載運算子「+」。

返回值 operator符號(引數列表);

我們先來過載運算子「=」使之能夠進行兩個物件的賦值操作,現在看看是怎麼使用的:

class str

};

這樣就可以用s1=s2;這樣的表示式了。

如何工作的?

其實是相當於呼叫了s1.operator=(s2);

為什麼需要返回乙個*this?

*this是當前這個物件,如果是void operator=(const str &s);那就使能s1=s2;而不能連續賦值了,

比如str s3;s3=s1=s2;對應:s3.operator=(s1.operator=(s2));這樣會出錯,因為operator=()方法的返回值如果是void,那s3.operator=()就沒有實參了。

接著我們過載運算子「+」 :

class str

else

cout << "size error!\n";

}};

在過載運算子「+」和「=」後,str類就可以這樣運算:

s3=s1+s2;

相當於s3.operator=(s1.operator+(s2));

因為s1.operator+(s2)會返回乙個臨時變數temp,所以s3.operator=()的引數不會為空。

運算子過載也是有限制的。

有些特別意義的符號無法過載,比如:?雙目運算子、.成員運算子、::作用域運算子、*指標運算子、#預處理命令等,這些都不可以過載,還有一些只可以是友元函式才能過載。

可以過載的表可以自己搜尋。

但是必須要使用物件與物件才能進行運算這有點麻煩,可否直接s3=s2+"primer";?

答案是可以的,但是必須定義乙個應對c指標的過載運算子"+":

class str

else

cout << "size error!\n";

}};

當遇到語句s3=s2+"primer";時,將被轉換為s3.operator=(s2.operator+("primer"));

挺不錯的,但是遇到這種情況該如何:

s3="primer"+s2;

對於表示式c=a+b和c=b+a是沒有區別的,但是在這裡"primer"不是str類的物件,它沒有operator+()這個方法,因此編譯器會報錯,不能使用"primer".operator+(s2)來替換該表示式。

也許你會突發奇想,定義乙個這樣的運算子:str operator+(const char *pstr,const str &s);

這是非法的,因為因為不知道是哪個物件呼叫,s3="primer"+s2;編譯器替換後就是s3.operator=("primer"+s2);然而s3的方法並不接受這樣的引數。

有一種比較好的方法,就是使用友元

firned 返回值 函式名(引數列表);

當乙個成員被宣告為友元時,該成員不再屬於類,但是卻和這個類的成員一樣具有訪問許可權。

class str

else

cout << "size error!\n";

}};

有了這個特殊的過載運算子後,就可以使用s3="primer"+s2;,對應呼叫s3.operator=(operator("primer",s2));

相當於定義了乙個叫operator+的函式一樣,只是編譯器會把char *+str自動轉換為operator("primer",s2);

但是對於有強迫症的我來說,使用.show()方法來輸出內容而不是cout顯得有點難受,能不能使用運算子過載讓編譯器檢查到cout《你很有想法,和我學 咳咳...

過載運算子《的確可以做到這個效果。

cout是ostream類的物件,而s3是str類的物件,也就是說cout.operator<<(s3)的過載運算子是這樣:

operator<<(ostream &os,const str &s);
於是先來實現這個方法:

class str

};

這裡為什麼需要返回乙個ostream物件的引用?

當我們進行簡單的輸出s3物件:cout《沒問題,正常工作。

但是我們想象通常的cout一樣連續輸出:cout<<"s3:"《這樣就會出錯。

一步一步來,先看看那cout<<"s3",相當於cout.operator<<("s3");,但是iostream裡面有定義它會返回乙個ostream物件,所以它的返回值是ostream物件,因此可以是

cout.operator<<("s3").operator<<(s3);它返回乙個ostream物件,然後這個ostream物件再呼叫.operator<<(s3)進行輸出。

然後你會發現如果str類的友元函式

operator<<(ostream &os, const str &s)

如果沒有返回值,那麼後面的<

如果要輸出s3的大小,那就必須喲呼叫該物件的getcount()方法,但是這樣太不美觀,而且不方便,

比如我想把大小賦給乙個int變數a:a=s3.setcount();

能不能做到這樣獲取呢:a=s3;

沒問題,但是這樣必須定義乙個轉換函式

operator 型別();

轉換函式沒有返回值與引數

class str

};

a=s3;

當編譯器發現右邊是str,而左邊是int時,就會檢查是否定義了與此匹配的轉換函式,並使用。

然而並非一定是int型,比如是double也會轉,因為int可以提公升轉換為double,所以會進行型別轉換。

運算子過載與友元

參考 c primer plus 第六版 先給段 include include using namespace std class time void addmin int m void addhr int h void reset int h 0,int m 0 time sum const t...

C 基礎 類的運算子過載與友元函式

函式格式 operatorop argument list operator 過載 運算子 operator 過載運算子 過載運算子,對類物件之間運算等 很方便,直接可以用 等呼叫 eg 申明 class ctime 使用 ctime a 2 ctime b a 1 a 0 a 1 sum a 0 ...

c 筆記 運算子過載和友元

過載的作用機理 過載的區別 成員函式與非成員函式 友元運算子過載是一種形式的c 多型,過載的概念擴充套件到了運算子上,允許賦予c 運算子多種含義,允許將運算子過載擴充套件到使用者定義的型別。編譯器將根據運算元的數目和型別決定使用哪種加法定義。過載的運算子 有些例外情況 不必是成員函式,但必須至少有乙...