1. 程式人生 > >C++11顯示型別轉換

C++11顯示型別轉換

1.隱式型別轉換的問題

隱式型別轉換是C++一個讓人又愛又恨的特性,使用方便,但可能會降低程式碼可讀性,甚至會造成一些十分隱晦的錯誤。

#include <iostream>
using namespace std;

class MyInt
{
public:
	//單參建構函式
	explicit MyInt(int value) :_value(value)
	{}

	//型別轉換操作符
	operator bool() const noexcept
	{
		return _value != 0;
	}

	//加運算子過載
	MyInt& operator+(const MyInt& right)
	{
		_value += right.getValue();
		return *this;
	}

	int getValue() const
	{
		return _value;
	}
private:
	int _value;
};

int main()
{
	MyInt myInt1(1);
	MyInt myInt2(2);
	cout << "myInt1+myInt2=" << myInt1 + myInt2 << endl;
	return 0;
} 

程式編譯執行輸出:

myInt1+myInt2=1

雖然程式編譯執行沒有什麼問題,但是兩個MyInt物件相加的結果並不是我們期望的數值3,而是1,導致這種隱晦錯誤的原因是在兩個MyInt物件相加後,結果物件myInt1被隱式地轉換為bool型別,導致輸出數值為1。隨著專案程式碼規模變大,這種由隱式型別轉換導致的隱晦錯誤會越埋越深,越來越難以發現。

2.顯示型別轉換

為了阻止容易導致隱晦錯誤的隱式型別轉換,C++11引入了explicit關鍵字作用於自定義的型別轉換操作符的功能,禁止隱式型別轉換。其用法類似於explicit作用於單參建構函式來避免單引數建構函式被隱式呼叫造成的隱式型別轉換。

//型別轉換操作符
explicit operator bool() const noexcept
{
	return _value != 0;
}

cout << "myInt1+myInt2=" << myInt1 + myInt2 << endl;		//編譯出錯

當使用explicit關鍵字修飾bool型別轉換操作符時,隱式型別轉換將會被阻止,進而引起上面的編譯錯誤,將潛在的隱晦錯誤暴露於編譯階段,讓錯誤得以提前發現,提前解決。

注意,顯式型別轉換有一個例外。如果表示式被用作條件,僅限轉換到bool,那麼顯式的operator bool()也可以隱式地進行。“被用作條件”指出現在以下語句:
(1)if、while及do語句的條件部分;
(2)for語句頭的條件表示式;
(3)邏輯非運算子(!)、邏輯或運算子(||)、邏輯與運算子(&&)的運算物件;
(4)條件運算子(x ? y : z)的條件表示式。

由於轉換到bool一般被用作條件,所以operator bool()一般用explicit來修飾。


參考文獻

[1]深入理解C++11[M].顯示轉換操作符
[2]【C++11】顯式轉換操作符