1. 程式人生 > >C++中的顯式建構函式

C++中的顯式建構函式

    有如下一個簡單的複數類:

class ClxComplex
{
public:
    ClxComplex(
double dReal =0.0double 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.00.0);

    其實,對於前兩行來說,編譯器都是把它們轉換成第3行的程式碼來實現的。因為我們寫了建構函式,編譯器就按照我們的建構函式來進行隱式轉換,直接把一個double數值隱式轉換成了一個ClxComplex的物件。可是,有些時候,我們不希望進行隱式轉換,或者隱式轉換會造成錯誤。比如下面的一個簡化的字串類:

class ClxString
{
public:
    ClxString(
int iLength);
    ClxString(
const
char*pString);
    
~ClxString();

private:
    
char*m_pString;
};

ClxString::ClxString(
int iLength)
{
    
if (iLength >0)
        m_pString 
=newchar[iLength];
}

ClxString::ClxString(
constchar*pString)
{
    m_pString 
=newchar[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:

class ClxString
{
public:
    
explicit ClxString(int iLength);
    ClxString(
constchar*pString);
    
~ClxString();

private:
    
char*m_pString;
};

    在這種情況下,要想用字串的長度來初始化一個ClxString物件,那就必須顯示的呼叫建構函式:

ClxString lxTest = ClxString(13);

    而下面這些程式碼將不能通過編譯。

ClxString lxTest =13
ClxString lxTest 
='A';