1. 程式人生 > >C++的explicit關鍵字

C++的explicit關鍵字

C++程式設計師對於explicit這個關鍵字其實不是很熟悉,至少我是如此;原因在於其使用範圍不大,而且作用也沒有那麼大。
但是這不是說明我們的程式中不需要這個關鍵字,按Google的C++程式設計規範和Effective C++的推薦看,我們最好將只有一個引數的建構函式都加上這個關鍵字,這同時也是cppcheck的要求。

explicit意味著明確的,確定的,這表明這個建構函式是無法隱式轉換的,其反義詞正式implicit。沒有了隱式轉換,我們則需要顯式使用某個型別的建構函式,如此,可以規避很多不那麼能拿得出手的外部類的呼叫。

指定建構函式或轉換函式(從c++ 11開始)是顯式的,也就是說,它不能用於隱式轉換和複製初始化

一個建構函式只有一個非預設引數(從c++ 11開始),沒有explicit宣告的,稱為轉換建構函式。

我們來看一個使用explicit 的程式碼


class explicitConstruct
{
public:
    explicitConstruct();
    explicitConstruct(int i){
        std::cout << "we use interger parameter is "<<i <<"\n";
    }
    explicitConstruct(int i,int j) {
        std::cout << "we use double interger parameter is "<<i<<" and "<<j<<"\n";
    }

};

class explicitConstructB
{
public:
    explicit explicitConstructB(int i){
        std::cout << "we use explicit explicitConstructB interger parameter is "<<i <<"\n";
    }
    explicit explicitConstructB(int i,int j){
        std::cout << "we use explicit explicitConstructB double interger parameter is "<<i<<" and "<<j<<"\n";
    }
    
};
};

explicitConstruct和explicitConstructB類的唯一區別是explicitConstructB的建構函式加入了explicit。
以下是測試程式碼

explicitConstruct i(3);//ok
explicitConstruct j(3,4); //ok
explicitConstructB ii(3);//ok
explicitConstructB jj(3,4);//ok

explicitConstruct k = 3;//ok
explicitConstruct l = {3,4};//ok

// explicitConstructB kk = 3; //error! copy-initialization does not consider explicitConstructB::explicitConstructB(int)
// explicitConstructB ll = {3,4};///error! copy-initialization does not consider explicitConstructB::explicitConstructB(int,int)
explicitConstructB kkk = explicitConstructB(3);//ok
explicitConstructB lll = explicitConstructB(3,4);//ok

測試程式碼很清楚的說明了explicit關鍵字發揮的作用,即讓類物件的構造過程無法使用隱式轉換的方式呼叫拷貝初始化。這樣做的好處在於,我們可以嚴格控制構造器引數的型別,避免發生歧義。