1、轉換分為到類類型與從類類型的轉換兩種。到類類型的轉換:通過轉換建構函式;從類類型的轉換:轉換操作符。
2、常用16個操作符:5個算術操作符(+、-、*、/、%)及其對應的複合賦值操作符,4 個關係操作符(<、<=、>、>=),以及相等操作符(==、!=)。
樣本
class SmallInt{public:SmallInt(int i = 0):val(i){//...}operator int() const {return val;} //轉換操作符函數,由SmallInt類類型轉換成int型。private:std::size_t val;};SmallInt si;double dval;si >= dval // si converted to int and then convert to doubleif (si) // si converted to int and then convert to bool
通用形式:operator type();
type表示內建類型名,類類型名或由類型別名所定義的名字。對任何可作為函數傳回型別的類型(除了void之外),都可以定義轉換函式。一般而言,不允許轉換為數組或函數類型,轉換為指標類型(資料或函數指標)及引用是可以的。
轉換操作符函數必須及必須是成員函數,不能指定傳回型別,形參表必須為空白。
類類型轉換不能傳遞(兩個都是自訂的轉換,而非內建類型的預設轉換),如A->B,B->C,但是我們不能把需要C型別參數的地方傳遞A類型的參數。
樣本
class SmallInt{public:SmallInt(int i = 0):val(i) //(轉換)建構函式{//...}operator int() const {return val;} //轉換操作符函數,由SmallInt類類型轉換成int型。private:std::size_t val;};class Integral {public:Integral(int i = 0): val(i) { }operator SmallInt() const { return val % 256; }private:std::size_t val;};int calc(int);Integral intVal;SmallInt si(intVal); // ok: convert intVal to SmallInt and copy to siint i = calc(si); // ok: convert si to int and call calcint j = calc(intVal); // error: no conversion to int from Integral
3、完全符合轉換比需要標準轉換的其他轉換更好。
4、轉換的二義性
樣本二義性
#include "iostream"#include "vector"#include "algorithm"#include "string"#include "functional"using namespace std;class Integral;class SmallInt{public:SmallInt(Integral){} //...};class Integral{public:operator SmallInt() const{}//...};void compute(SmallInt);int main(){Integral int_val;compute(int_val); //error:ambiguous}
避免二義性最好的方法是避免編寫互相提供隱式轉換的成對的類。保證最多隻有一種途經將一個類型轉換成另一個類型。
可以通過顯式強制消除二義性。
樣本
#include "iostream"#include "vector"#include "algorithm"#include "string"#include "functional"using namespace std;class SmallInt {public:// Conversions to int or double from SmallInt// Usually it is unwise to define conversions to multiple arithmetic typesoperator int() const { return val; }operator double() const { return val; }// ...private:std::size_t val;};void compute(int);void compute(double);void compute(long double);int main(){SmallInt si;//compute(si); // error: ambiguous//compute(static_cast<int>(si)); //ok, call compute(int)}
有調用重載函數時,需要使用建構函式或強制類型轉換來轉換實參是拙劣設計的表現。
5、操作符的重載確定,三步:
1)選擇候選函數。
2)選擇可行函數,包括識別每個實參的潛在轉換序列。
3)選擇首選的函數。
6、幾個經驗
1)不要定義相互轉換的類,即如果類 Foo 具有接受類 Bar 的對象的建構函式,不要再為類 Bar 定義到類型 Foo 的轉換操作符。
2)避免到內建算術類型的轉換。具體而言,如果定義了到算術類型的轉換,則
o不要定義接受算術類型的操作符的重載版本。如果使用者需要使用這些操作符,轉換操作符將轉換你所定義的類型的對象,然後可以使用內建操作符。
o不要定義轉換到一個以上算術類型的轉換。讓標準轉換提供到其他算術類型的轉換。
最簡單的規則是:對於那些“明顯正確”的,應避免定義轉換函式並限制非顯式建構函式。
參考
[1] http://blog.163.com/zhoumhan_0351/blog/static/3995422720103182106992/
[2] http://blog.163.com/zhoumhan_0351/blog/static/3995422720100284731826/
[3] http://blog.163.com/zhoumhan_0351/blog/static/3995422720104931348260/