有以下一個簡單的複數類:函數
class ClxComplex { public: ClxComplex(double dReal = 0.0, double dImage = 0.0) { m_dReal = dReal; dImage = dImage; } double GetReal() const { return m_dReal; } double GetImage() const { return m_dImage; } private: double m_dReal; double m_dImage; };
咱們知道,下面的3行代碼是等價的:spa
ClxComplex lxTest = 2.0; ClxComplex lxTest = ClxComplex(2.0); ClxComplex lxTest = ClxComplex(2.0, 0.0);
其實,對於前兩行來講,編譯器都是把它們轉換成第3行的代碼來實現的。由於咱們寫了構造函數,編譯器就按照咱們的構造函數來進行隱式轉換,直接把一個double數值隱式轉換成了一個ClxComplex的對象。但是,有些時候,咱們不但願進行隱式轉換,或者隱式轉換會形成錯誤。好比下面的一個簡化的字符串類:code
class ClxString { public: ClxString(int iLength); ClxString(const char *pString); ~ClxString(); private: char *m_pString; }; ClxString::ClxString(int iLength) { if (iLength > 0) m_pString = new char[iLength]; } ClxString::ClxString(const char *pString) { m_pString = new char[strlen(pString)]; strcpy(m_pString, pString); } ClxString::~ClxString() { if (m_pString != NULL) delete m_pString; }
咱們能夠用字符串的長度來初始化一個ClxString的對象,可是咱們卻不但願看到下面的代碼:對象
ClxString lxTest = 13; // 等同於ClxString lxTest = ClxString(13);
這會給閱讀代碼形成沒必要要的歧義。
還有,咱們知道下面的代碼是用字符串A來初始化一個ClxString的對象:blog
ClxString lxTest = "A"; // 等同於ClxString lxTest = ClxString("A");
但是,若是有人寫成:
ClxString lxTest = 'A'; // 等同於ClxString lxTest = ClxString(65);
那上面的代碼就會初始化一個長度爲65(字母A的ASCII碼值,在C和C++中,字符是以ASCII值存儲的)的字符串。
固然,上面的狀況都不是咱們但願看到的。在這個時候咱們就要用到顯示構造函數了。
將構造函數聲明成explicit就能夠防止隱式轉換。
下面是使用顯示構造函數的ClxString:ci
class ClxString { public: explicit ClxString(int iLength); ClxString(const char *pString); ~ClxString(); private: char *m_pString; };
在這種狀況下,要想用字符串的長度來初始化一個ClxString對象,那就必須顯示的調用構造函數:字符串
ClxString lxTest = ClxString(13);
而下面這些代碼將不能經過編譯。
ClxString lxTest = 13; ClxString lxTest = 'A';