15 More Effectic C++ ——條款21/22(過載防止隱式型別轉換/使用複合操作符)
阿新 • • 發佈:2018-12-26
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; }