1. 程式人生 > >C++中explicit關鍵字的作用

C++中explicit關鍵字的作用

explicit用來防止由建構函式定義的隱式轉換。

 

要明白它的作用,首先要了解隱式轉換:可以用單個實參來呼叫的建構函式定義了從形參型別到該類型別的一個隱式轉換。

例如:

 

複製程式碼
class things
{
public:
things(
const std::string&name =""):
m_name(name),height(
0),weight(10){}
int CompareTo(const things & other);
std::
string m_name;
int height;
int weight;
};
複製程式碼

 

  

 

這裡things的建構函式可以只用一個實參完成初始化。所以可以進行一個隱式轉換,像下面這樣:

things a;
................
//在這裡被初始化並使用。
std::string nm ="book_1";
//由於可以隱式轉換,所以可以下面這樣使用
int result = a.CompareTo(nm);

  這段程式使用一個string型別物件作為實參傳給things的CompareTo函式。這個函式本來是需要一個tings物件作為實參。現在編譯器使用string nm來構造並初始化一個

 things物件,新生成的臨時的things物件被傳遞給CompareTo函式,並在離開這段函式後被析構。

 

  這種行為的正確與否取決於業務需要。假如你只是想測試一下a的重量與10的大小之比,這麼做也許是方便的。但是假如在CompareTo函式中還涉及到了要除以初始化為0的height屬性,那麼這麼做可能就是錯誤的。需要在構造tings之後更改height屬性不為0。所以要限制這種隱式型別轉換。

  那麼這時候就可以通過將建構函式宣告為explicit,來防止隱式型別轉換。

  explicit關鍵字只能用於類內部的建構函式宣告上,而不能用在類外部的函式定義上。現在things類像這樣:

複製程式碼
class things
{
public:
explicit things(const std::string&name =""):
m_name(name),height(
0),weight(0){}
int CompareTo(const things & other);
std::
string m_name;
int height;
int weight;
};
複製程式碼

  這時再進行編譯,在vs2008上會提示:沒有可用於執行該轉換的使用者定義的轉換運算子,或者無法呼叫該運算子。

  這時你仍然可以通過顯示使用建構函式完成上面的型別轉換:

things a;
................
//在這裡被初始化並使用。
std::string nm ="book_1";
//顯示使用建構函式
int result = a.CompareTo(things(nm));

  google的c++規範中提到explicit的優點是可以避免不合時宜的型別變換,缺點無。所以google約定所有單引數的建構函式都必須是顯示的,只有極少數情況下拷貝建構函式可以不宣告稱explicit。例如作為其他類的透明包裝器的類。

 

  effective c++中說:被宣告為explicit的建構函式通常比其non-explicit兄弟更受歡迎。因為它們禁止編譯器執行非預期(往往也不被期望)的型別轉換。除非我有一個好理由允許建構函式被用於隱式型別轉換,否則我會把它宣告為explicit。我鼓勵你遵循相同的政策.