C++中的顯式構造函數 收藏
以兩個C++的小例子來說明怎樣通過使用顯式構造函數來防止隐式轉換。
有如下一個簡單的複數類:
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行代碼是等價的:
ClxComplex lxTest = 2.0;
ClxComplex lxTest = ClxComplex(2.0);
ClxComplex lxTest = ClxComplex(2.0, 0.0);
其實,對于前兩行來說,編譯器都是把它們轉換成第3行的代碼來實作的。因為我們寫了構造函數,編譯器就按照我們的構造函數來進行隐式轉換,直接把一個double數值隐式轉換成了一個ClxComplex的對象。可是,有些時候,我們不希望進行隐式轉換,或者隐式轉換會造成錯誤。比如下面的一個簡化的字元串類:
class ClxString
ClxString(int iLength);
ClxString(const char *pString);
~ClxString();
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的對象:
ClxString lxTest = "A"; // 等同于ClxString lxTest = ClxString("A");
可是,如果有人寫成:
ClxString lxTest = 'A'; // 等同于ClxString lxTest = ClxString(65);
那上面的代碼就會初始化一個長度為65(字母A的ASCII碼值,在C和C++中,字元是以ASCII值存儲的)的字元串。
當然,上面的情況都不是我們希望看到的。在這個時候我們就要用到顯示構造函數了。
将構造函數聲明成explicit就可以防止隐式轉換。
下面是使用顯示構造函數的ClxString:
explicit ClxString(int iLength);
在這種情況下,要想用字元串的長度來初始化一個ClxString對象,那就必須顯示的調用構造函數:
ClxString lxTest = ClxString(13);
而下面這些代碼将不能通過編譯。
ClxString lxTest = 13;
ClxString lxTest = 'A';