C 中explicit關鍵字詳解

2021-10-02 02:56:20 字數 3793 閱讀 8220

展開

總結參考文獻

explicit關鍵字的作用

explicit關鍵字在寫程式時使用的次數較少,但是仔細觀察會發現,在c++標準庫中的相關類宣告中explicit出現的頻率是很高的,那麼explicit關鍵字到底有什麼作用呢?接下來我就為大家一一解答.

explicit為清晰的;明確的之意.顧名思義,關鍵字explicit可以阻止隱式轉換的發生.

例如: c++中只帶有乙個引數的建構函式,或者或者除了第乙個引數外其餘引數都有預設值的多參建構函式,承擔了兩個角色:

1.用於構建單引數的類物件.

2.隱含的型別轉換操作符.

例如:乙個類a的建構函式a(int i)就是,既可以用來作為構造器,又可以實現隱式轉換a a=1;因為1可以通過建構函式a(int i)轉換為乙個類a的物件。(隱含的型別轉換操作符)

但有時我們並不想讓他進行隱式型別轉換,這時c++的explicit關鍵字就起到作用了.

#includeusing namespace std;

class fraction

operator double() const

private:

int m_numerator;

int m_denominator;

}int main(void)

我們設計了乙個fraction類(分數類), 在主函式中定義了乙個分數物件f,然後將3.5 + f賦值給double型別變數d, 但是我們發現f並不是乙個double型別的變數,因此編譯器會從fraction類中尋找operator double()函式,隱式呼叫該函式將fraction型別轉換成乙個double型別. operator double()就是我們所說的型別轉換函式(type conversion function).

型別轉換函式的一般形式

operator 資料型別 const()

1.轉換函式必須是類的成員函式

2.轉換函式不能宣告返回型別

3.形參列表必須為空

4.型別轉換函式通常應該是const

當我們想要在明確宣告型別轉換的時候,才使用型別轉化函式時,這時我們就需要使用到explicit關鍵字了.使用方法如下:

#includeusing namespace std;

class fraction

explicit operator double() const

private:

int m_numerator;

int m_denominator;

}int main(void)

注意,這時當我們想呼叫型別轉換函式的時候,需要寫成static_cast(f);

注意static_cast 是c++11 引入的型別轉換運算子.

單運算元建構函式

還是採用上面的fraction類,這次我們過載(overload) 「+」 號運算子,使得仍然可以達到相同的效果.

#includeusing namespace std

class fraction

double operator+(const fraction& a)

private:

int m_numerator;

int m_denominator; } 

int main(void)

在double d = f + 3 這句話中建構函式就是前面所提到的第二種角色隱含的型別轉換操作符.,因為執行到這句話首先會呼叫+的過載函式,該函式的呼叫物件預設為左運算元,右運算元為fraction型別,因此會呼叫建構函式將3轉換成fraction型別,然後將得到的返回值double型別賦值給變數d.

同理如果不想讓建構函式進行隱式型別轉換,可以在建構函式前面加上explicit關鍵字,防止進行隱式轉換.使用方法如下:

#includeusing namespace std

class fraction

double operator+(const fraction& a)

private:

int m_numerator;

int m_denominator; } 

int main(void)

你可能會注意到,加上explicit 關鍵字之後,這個**將不能正確執行.

同時出現拷貝建構函式和型別轉換函式

我們看如下一段**:

#includeusing namespace std

class fraction

operator int()

int operator+(const fraction& a)

private:

int m_numerator;

int m_denominator; } 

int main(void)

這時你會發現會產生乙個二義性問題,在執行int d = f + 3的時候到底是該選擇型別轉換函式,將f轉換成int型別再繼續運算呢?還是應該將3作為建構函式的引數進行隱式轉換,然後再呼叫+運算子過載函式呢?

解決這個問題的辦法就是使用explicit關鍵字限制,具體方法有兩種你:

1.在建構函式前面加上explicit關鍵字, 防止int型別隱式轉換成為fraction型別.

2.在型別轉換函式前面加上explicit關鍵字,這樣只有顯示呼叫型別轉換static_cast(f)時,才會呼叫該函式.

拷貝建構函式

copy constructor也是同樣的,如果copy constructor被宣告為explicit,則這個類物件不能隱式呼叫,用於傳參傳遞和函式返回值.

//隱式呼叫 

complexv1(1.2, 2.3);  

complexv2 = v1;        // 編譯錯誤 c2558  

//引數按值傳遞

void func(complexv);  

func(v1);                       // 編譯錯誤 c2664  

//返回值按值傳遞

complexfunc()  

總結c++中,乙個引數的建構函式(或者除了第乙個引數外其餘引數都有預設值的多參建構函式),承擔了兩個角色。

用於構建單引數的類物件

隱含的型別轉換操作符

explicit關鍵字只對有乙個引數的類建構函式有效, 如果類構造函式引數大於或等於兩個時, 是不會產生隱式轉換的, 所以explicit關鍵字也就無效了

宣告為explicit的建構函式不能在隱式轉換中使用,只能顯示呼叫,去構造乙個類物件。

base base(『a』) //顯示呼叫,ok

base base = 『a』 //隱是呼叫,err

盡量避免有二義性的型別轉換,如果類中包含乙個或多個隱式型別轉換,則必需使用explicit關鍵字確保在類型別和目標型別之間只存在唯一一種隱式轉換方式,否則將出現二義性。

但是將拷貝建構函式宣告成explicit並不是良好的設計,一般只將有單個引數的constructor宣告為explicit,而copy constructor不要宣告為explicit.

參考文獻

本文主要參考了如下三個文章,對其進行了總結

c++ 型別轉換函式 與 explicit

c++學習之explicit關鍵字詳解

c++ explicit關鍵字詳解

c++ 物件構造, 拷貝, 賦值和隱式型別轉換總結

詳解 c 關鍵字 explicit

用了很久的c 了,今天突然被小夥伴問道,建構函式前的explicit 關鍵字什麼作用,於是自己也只能支支吾吾的說出 為了顯式呼叫 很尷尬啊 典型的知道所以然不知道其所以然 好吧,搜搜資料好好地充充電 首先說定義,c 中的explicit關鍵字只能用於修飾只有乙個引數的類建構函式,它的作用是表明該建構...

c 中explicit關鍵字

c 中的explicit關鍵字用來修飾類的建構函式,表明該建構函式是顯式的。既然有 顯式 那麼必然就有 隱式 那麼什麼是顯示而什麼又是隱式的呢?按照預設規定,只有乙個引數的建構函式也定義了乙個隱式轉換,將該建構函式對應資料型別的資料轉換為該類物件,如下面所示 include using namesp...

c 中的explicit關鍵字

c 中的explicit關鍵字 c 中的explicit關鍵字用來修飾類的建構函式,表明該建構函式是顯式的,既然有 顯式 那麼必然就有 隱式 那麼什麼是顯示而什麼又是隱式的呢?如果c 類的建構函式有乙個引數,那麼在編譯的時候就會有乙個預設的轉換操作 將該建構函式對應資料型別的資料轉換為該類物件,如下...