1. 程式人生 > >15 More Effectic C++ ——條款21/22(過載防止隱式型別轉換/使用複合操作符)

15 More Effectic C++ ——條款21/22(過載防止隱式型別轉換/使用複合操作符)

1 看不見的隱式型別轉換

當建構函式只有一個,編譯器會利用建構函式進行隱式型別轉換。如下面所示:

class UInt {
	public:
		UInt();
		UInt(int value);
}
UInt a = 0, b(0), c = 1; // 隱式轉換:int變成UInt型別
UInt d = 1 + a; // 隱式型別轉換

這種隱式型別轉換十分危險,當有多種類似"UInt(int value)"函式被宣告時,比如“UInt(SomeType value)”,就會造成比較嚴重的邏輯錯誤——誤呼叫隱式型別轉換。

為了消除這種危險,可以採用以下兩種方法。但是,不推薦使用大量過載函式,會使軟體更難維護。

方法1:使用explicit關鍵字

explicit關鍵字需要使用者明確指出型別轉換。

class UInt {
	public:
		Unit();
		explicit UInt(int a);
}
UInt a = 1 + b; //錯誤,沒有明確指出1的型別。
UInt a = UInt(1) + b; //正確,明確指出型別。

方法2:利用函式過載

如下,過載函式通過不同函式簽名來識別。較低版本中,函式簽名只依據傳入引數的不同來識別。

const UInt operator+(int lhs, const UInt& rhs);
const UInt operator+(const UInt& lhs, int rhs);
const UInt operator+(const UInt& lhs, const UInt& rhs);
// 以上都正確,下面錯誤
const UInt operator+(int lhs, int rhs); // 過載的和庫中的簽名一致,錯誤。

2 複合操作符與其單獨形式

C++允許我們過載+, -, *, /四種操作符,他們對應的複合操作符為:+=, -=, *=, /=。這8個操作符允許使用者進行過載。由於單獨操作符會涉及如下兩個步驟,複合操作符只涉及第1步,因此具體運算可以直接使用複合操作符。

1,運算
2,獲得運算結果,並存儲在臨時變數中,返回臨時變數。

具體程式碼如下:

class MyClass {
	public:
		MyClass& operator += (const MyClass& rhs)
		{
			// do something
			return *this;
		}
}
const MyClass operator + (const MyClass& lhs, const MyClass& rhs)
{
	return MyClass(lhs) += rhs;
}
// 進一步,可以使用template來實現
template<class T>
const T operator +(const T& lhs, const T& rhs)
{
	return T(lhs) += rhs;
}