1. 程式人生 > >C++ explicit關鍵字:禁止隱式轉換

C++ explicit關鍵字:禁止隱式轉換

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

要明白這個關鍵字的含義,首先我們要知道class型別的物件的隱式轉換:可以用單個實參來呼叫的建構函式定義了從形參型別到該類型別的一個隱式轉換。

比如:

class SomeBody{
public:
	SomeBody(const std::string& name =""):
              m_name(name),height(0),weight(10){}
	int CompareTo(const SomeBody& other);
	std::string m_name;
int height; int weight; }

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

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

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

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

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

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

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

class SomeBody{
public:
    explicit SomeBody(const std::string&name =""):
          m_name(name),height(0),weight(0){}
    int CompareTo(const SomeBody & other);
    std::string m_name;
    int height;
    int weight;
};

這個時候再對業務程式碼編譯就會提示編譯錯誤。

但是我們仍然可以通過顯示使用建構函式完成上面的型別轉換:

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

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

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

參考:https://www.cnblogs.com/winnersun/archive/2011/07/16/2108440.html