首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ explicit 關鍵字詳解:禁止構造函數隱式轉換

     編輯:關於C++

問題現象

class A { public: A(int a) : data(a) {} int data; };
class B { public: explicit B(int b) : data(b) {} int data; };

void func_a() { A a = 0; a = 1; }  // 編譯通過
void func_b() { B b = 0; b = 1; }  // 編譯錯誤:no match for 'operator='

A a = 0 觸發 隱式轉換:編譯器構建臨時 A(0) 再調用拷貝構造。B 標記 explicit 禁止此行為。

隱式轉換觸發場景

  1. 拷貝初始化:T obj = value;
  2. 函數參數傳遞:void f(T); f(123);
  3. 返回值隱式轉換:T f() { return 123; }
  4. 標準庫容器插入:vector v; v.push_back(123);

explicit 作用機制

  • 標記單參數構造函數(或多參數但有默認值),禁止隱式轉換,只允許直接初始化:T obj(value);、T obj{value};、static_cast<T>(value)。
  • C++11 起支持多參數構造函數加 explicit,防止列表初始化隱式轉換。

性能與語義考量

A a = 0;  // 相當於 A tmp(0); A a = tmp;  兩次構造+一次拷貝(可能優化)
A a(0);   // 直接構造,零開銷

隱式轉換可能產生臨時對象拷貝開銷,且語義模糊(func(10) 是調用 func(int) 還是 func(A)?)。explicit 強制調用者明確意圖。

最佳實踐

  1. 單參數構造函數默認加 explicit,除非確需隱式轉換語義(如智能指針、包裝類型)。
  2. 轉換構造函數(如 string(const char*))通常保持隱式,便於字面值賦值。
  3. C++11 explicit operator bool() 防止布爾上下文意外轉換(如 if (ptr) 允許,但 ptr + 1 禁止)。
  4. 工廠函數/命名構造函數替代隱式轉換:static A Create(int);

常見誤區

  • explicit 不影響拷貝/移動構造函數(多參數)。
  • explicit 不禁止 static_cast、T{val}、直接初始化。
  • 繼承類構造函數繼承基類 explicit 屬性(C++11 繼承構造函數)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved