首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ explicit 關鍵字:禁止構造函數隱式轉換的用法與必要性

     編輯:程式設計綜合問答

C++ Primer P461 explicit Message(const std::string& str = "") 中的 explicit 禁止單參數構造函數參與隱式類型轉換,避免意外調用導致邏輯錯誤或性能損耗。

隱式轉換示例


class Message {
public:
    // 無 explicit
    Message(const std::string& str = "") : content(str) {}
    std::string content;
};

void printMessage(const Message& msg) {
    std::cout << msg.content << std::endl;
}

int main() {
    printMessage("Hello"); // 隱式調用 Message("Hello") 創建臨時對象
    // 等價於 printMessage(Message("Hello"));
}

編譯器自動將 const char* → std::string → Message,創建臨時對象。若構造函數耗時(讀文件、分配內存),會在不知情下產生開銷。

加上 explicit 後


class Message {
public:
    explicit Message(const std::string& str = "") : content(str) {}
    // ...
};

void printMessage(const Message& msg);

int main() {
    printMessage("Hello"); // 編譯錯誤:無法從 const char* 隱式轉換
    printMessage(Message("Hello")); // 必須顯式構造
    printMessage(std::string("Hello")); // 或先轉 string
}

explicit 適用場景

場景是否加 explicit理由
單參數構造函數✅ 默認加防止意外隱式轉換
多參數構造函數❌ 不需要無法隱式調用(C++11 前)
拷貝/移動構造函數❌ 禁用會導致傳值/返回值失效
轉換構造函數(有意設計)❌ 不加如智能指針從裸指針構造
C++11 列表初始化構造函數✅ 建議加防止 {...} 隱式縮窄轉換

C++11 新特性:explicit 轉換函數


class BigInt {
    long long val;
public:
    BigInt(long long v) : val(v) {}
    
    // 禁止隱式轉換為 bool,但允許顯式轉換
    explicit operator bool() const { return val != 0; }
};

void func(bool flag);

BigInt n(42);
if (n) { }           // OK: 語境轉換允許 explicit operator bool
func(n);             // 錯誤: 隱式轉換被禁止
func((bool)n);       // OK: 顯式轉換
func(static_cast(n)); // OK

最佳實踐

  1. 默認給所有單參數構造函數加 explicit
  2. 只有確需要隱式轉換時(如數值包裝類、智能指針)才移除
  3. 代碼審查檢查點:所有構造函數是否按意圖標註 explicit
  4. 現代 C++:配合 explicit operator Type() 控制外向轉換

總結

explicit 含義:**「這個構造函數/轉換函數僅供顯式調用,編譯器不得自動應用」**。C++ Primer 示例中為 Message 加 explicit,防止 const char* 經 std::string 隱式構造 Message 臨時對象,體現「顯式優於隱式」的現代 C++ 設計哲學。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved