天天看點

【轉】C++中的顯式構造函數

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';

繼續閱讀