@著作權歸作者所有:來自CSDN博客作者大鬍子的艾娃的原創作品,如需轉載,請註明出處https://blog.csdn.net/qq_43148810,否則將追究法律責任。
如有錯誤的地方歡迎指正,謝謝!
1、C++中的關鍵字explicit主要是用來修飾類的構造函數,被修飾的構造函數的類,不能發生相應的隱式類型轉換,只能以顯示的方式進行類型轉換。類構造函數默認情況下聲明爲隱式的即implicit。隱式轉換即是可以由單個實參來調用的構造函數定義了一個從形參類型到該類類型的隱式轉換。編譯器在試圖編譯某一條語句時,如果某一函數的參數類型不匹配,編譯器就會嘗試進行隱式轉換,如果隱式轉換後能正確編譯,編譯器就會繼續執行編譯過程,否則報錯。
2、explicit關鍵字只能用於類內部的構造函數聲明上,而不能用在類外部的函數定義(函數實現)上,它的作用是不能進行隱式轉換;explicit關鍵字作用於單個參數的構造函數,如果構造函數有多個參數,但是從第二個參數開始,如果各參數均有默認賦值,也可以應用explicit關鍵字。
3、 當構造函數只有一個參數時,會進行自動隱式轉換,當構造函數參數個數超過或等於兩個時自動取消隱式轉換,當只有一個必須輸入的參數,其餘的爲有默認值的參數時使用explicit也起作用。
4、一般只將有單個參數的構造函數聲明爲explicit,而拷貝構造函數不要聲明爲explicit。explicit關鍵字只能對用戶自己定義的對象起作用,不對默認構造函數起作用。此關鍵只能夠修飾構造函數。無參數的構造函數和多參數的構造函數總是顯示調用,這種情況在構造函數前加explicit無意義。
5、當不希望進行自動類型轉換時用explicit,標準庫的許多構造函數都是explicit的。
我們通過例子來直觀的說明:
#include <iostream>
using namespace std;
class A
{
public:
A(int i = 5)
{
m_a = i;
}
private:
int m_a;
};
int main()
{
A s;
//我們會發現,我們沒有重載'='運算符,但是卻可以把內置的int類型賦值給了對象A.
s = 10;
//實際上,10被隱式轉換成了下面的形式,所以才能這樣.
//s = A temp(10);
system("pause");
return 0;
}
此時,我們發現s的成員變量m_a已將被更改了。
看看我們在類A的構造函數前加上explicit關鍵字會發生什麼。
#include <iostream>
using namespace std;
class A
{
public:
//這裏用explicit關鍵詞來修飾類構造函數.
explicit A(int i = 5, int j = 10)
{
m_a = i;
m_b = j;
}
private:
int m_a;
int m_b;
};
int main()
{
A s;
//這樣直接賦值,會被提示錯誤,因爲explicit抑制隱式轉換的進行
s = 10;//這樣會報錯!!!
//當然顯示轉換還是可以的.
s = A(20);
system("pause");
return 0;
}
再來看一個例子。
#include <iostream>
using namespace std;
class Test1
{
public :
Test1(int num):n(num){}
private:
int n;
};
class Test2
{
public :
explicit Test2(int num):n(num){}
private:
int n;
};
int main()
{
Test1 t1 = 12;
Test2 t2(13);
Test2 t3 = 14;
return 0;
}
編譯時t3那一行會報錯:提示:無法從“int”轉化爲“Test2”。註釋掉t3那一行,t1能編譯通過,調試時發現t1中的成員變量n已被賦值成功。
通過以上兩個例子我們可得:對於僅有一個參數或除第一個參數外其餘參數均有默認值的類構造函數,儘可能使用explicit關鍵字修飾。
另注意:當類的構造函數的聲明和定義分別在兩個文件裏時,explicit只能寫在構造函數的聲明中,不能寫在定義中。
更多內容請關注個人博客:https://blog.csdn.net/qq_43148810