C++提供關鍵字explicit,可以阻止不應該允許的經過轉換構造函數進行的隱式轉換發生.
聲明為explicit的構造函數不能在隱式轉換中使用.
C++中,一個參數的構造函數(或者除了第一個參數外其余參數都有默認值的多參構造函數),承擔了兩個角色.
1.是個構造器,2.是個默認且隱含的類型轉換操作符.
寫下如AAA = XXX,這樣的代碼,且恰好XXX的類型正好是AAA單參數構造的參數類型,這時候編譯器就自動調用這個構造器,創建一個AAA的對象.
使用explicit聲明構造函數,則可防止隱式轉換,避免上述情況的發生.具體例子如下:
1 class CTest1 { 2 public: 3 CTest1(int n) 4 { 5 cout<<"Constructor of CTest1"<<endl; 6 } 7 CTest1(const CTest1&) 8 { 9 cout<<"Copy constructor of CTest1"<<endl; 10 } 11 }; 12 class CTest2 { 13 public: 14 explicit CTest2(int n) 15 { 16 cout<<"Constructor of CTest2"<<endl; 17 } 18 explicit CTest2(const CTest2&) 19 { 20 cout<<"Copy constructor of CTest2"<<endl; 21 } 22 }; 23 int main() 24 { 25 CTest1 a1(1); //顯示調用構造函數 26 CTest1 b1 = 1; //隱式調用構造函數 27 CTest1 c1 = a1; //隱式調用拷貝構造函數 28 CTest1 d1(b1); //顯示調用拷貝構造函數 29 CTest2 a2(2); //顯示調用構造函數 30 CTest2 b2 = 2; //隱式調用構造函數,編譯錯誤 31 CTest2 c2 = a2; //隱式調用拷貝構造函數,編譯錯誤 32 CTest2 d2(b2); //顯示調用拷貝構造函數 33 return 0; 34 }
如第26行代碼所示,是直接隱式調用構造函數,創建對象b1,不要誤理解為是先隱式調用構造函數創建臨時對象,將調用拷貝構造函數,以臨時對象創建對象b1.
如第31行代碼所示,explicit對拷貝構造函數也會限制作用,將會阻隱式拷貝構造函數的調用.
將拷貝構造函數聲明為explicit,則會阻止隱式拷貝構造函數的調用.隱式拷貝構造函數的調用主要發生在三個點:
1.一個對象作為函數參數,以值傳遞的方式傳入函數體.
2.一個對象作為函數返回值,以值傳遞的方式從函數返回.
3.以AAA = xxx的方式創建對象AAA,xxx為與AAA為同類型的對象.
因而,將拷貝構造函數聲明成explicit並不是良好的設計,一般只將有單個參數的constructor聲明為explicit,而copy constructor不要聲明為explicit.