從零開始學習c++之運算符重載與類型轉換

運算符重載:

什麼是運算符重載:

重載的運算符是特殊名字的函數,名字由operator關鍵字加上要重載的運算符組成,如operator+,和其他函數一樣,重載的運算符也包含返回類型、參數列表和函數體。


運算符重載的使用細節:

(1)當一個運算符函數是成員函數,this綁定到了左側運算對象。成員運算符函數的(顯式)參數數量比運算對象的數量少一個。

(2)除了重載的函數調用運算符operator()之外,其他重載運算符不能含有默認實參。

(3)只能重載現有的運算符,無權發明新的運算符。

(4)運算符的重載不改變運算符優先級。


可以被重載的運算符:

+   -    *    /    %    ^    &    |    ~    !    ,    =    <    >    <=    >=    ++    --    <<    >>    ==    !=    &&    ||    ++    -=    /=    %=    &=    ^=    |=

*=    <<=    >>=    []    ()    ->    ->*    new    new[]    delete    delete[]


不可以重載的運算符:

           ::            .*              .            ?:


調用重載運算符:

data1 + data2;    //普通表達式
operator+(data1,data2);   //等價的函數調用
//這兩條語句式等價的,都調用了非成員函數operator+,傳入data1和data2作爲兩個參數
data3 += data4      //基於調用的表達式
data3.operator+=(data2);         //對成員運算符的等價調用
//這兩條語句都調用了成員函數 operator+= ,將this綁定到data3的地址,將data4作爲實參傳入了函數 


重載運算符作爲成員函數和非成員函數的選擇:

(1)單目運算符應該作爲成員函數(不是必須)
(2)= () [] -> ->*必須是成員函數
(3)複合賦值運算符應該作爲成員函數
(4)所有其他不是這些二元的運算符應該作爲非成員函數


賦值運算符重載標準格式:

T& T::operator=(const T& rhs) {
if (this != &rhs)             //檢測自身不等於要賦值的對象
{
//perform assignment
}
return *this;
}


示例代碼:

class Integer {
public :
	Integer(int n = 0):i(n){}
	const Integer operator+(const Integer& n) const {
		return Integer(i + n.i);
	}
	int print() { return i; }
private:
	int i;
};
int main()
{
	Integer x(5), y(10), z1,z2,z3;

	z1 = x + y;                  //等同於 z = x.operator+(y)
	z2 = x + 3;                  //Integer類內構造函數被調用Integer(3):i(3){},後z = x.operator+(3)
	//z3 = 3 + y;                  //編譯不通過,3爲第一個參數所以調用int型+,y不爲int型且Integer類內沒有方法把y變爲int型參數
 
	cout <<"Z1:"<< z1.print() << "\tZ2:" << z2.print() << endl;
   return 0;
}



類型轉換:

什麼是類型轉換:

類型轉換運算符是類的一種特殊成員函數,它負責將一個類類型的之轉換成其他類型。
標準格式:operator type() const;              //type表示某種類型


類型轉換運算符與構造函數:

類型轉換和構造函數都能作T => C的類類型轉換

(1)T(C)                                 //構造函數
(2)operator T() const;          //C中的類型轉換 

class Orange;
class Apple {
public:
	operator Orange() const {}    //類型轉換
};

class Orange {
public:
	Orange(Apple) {}       //構造函數     
};

void func(Orange){}     //func函數參數爲Orange
int main()
{
    Apple ap;
    func(ap);                  //編譯不通過,報錯:應用多個用戶定義的從Apple到Orange的轉換
    return 0;
}
但是當構造函數與類型轉換同時存在時,編譯器無法知曉應使用哪種函數來進行轉換,導致錯誤。

解決方法:(1)去掉其中一個函數。

                  (2)在構造函數前加explicit關鍵字,表示此構造函數只能用於構造,不能用於自動類型轉換

小結:

應避免過度使用類型轉換函數,因其容易形成誤導性,所以要防止意外的事情發生。

一般使用一個專門的函數來調用進行類型轉換,使程序更加一目瞭然發生了什麼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章