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。我鼓勵你遵循相同的政策。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM