參考自 狄泰 c++深度解析
我們知道在標準的資料型別之間是有隱式轉換的,轉換關係如下:
這是 c語言和 c++ 裡的轉換關係,我們這裡主要談論c++,總所周知c++相比c語言有了乙個類的概念,類中有建構函式,而當建構函式具有以下特點時會成為轉換建構函式:
有且只有乙個引數
引數是基本資料型別
引數不是自身類的型別
我們知道,類也是乙個資料型別,那麼問題來了類和標誌資料型別可否相互轉換?
先看下面**:
class
test
;int
main()
上面的**編譯實際上是會報錯的
那麼稍作修改看看
class
test};
intmain()
很有趣,竟然通過了, 這是為什麼呢?
實際上,這是編譯器的行為,編譯器會盡量的讓**通過,會進行隱轉換,怎麼轉換?首先編譯器看到5這個整型數那麼很明顯是不能直接賦值到 t 變數的,所以編譯器會尋找轉換建構函式,編譯器發現在test 類中正好存在轉換建構函式test(int a), 於是將 t = 5 轉換為 t = test(5) 所以編譯就會通過
ok, 我們再看看下面的修改:
class
test
test operator
+(test& e)};
intmain()
上面**編譯結果是什麼?
10
這是為什麼可以編譯通過,有輸出?
原理其實和上面紅字所說一樣, 在編譯到 r = t + 5 時候, 編譯器發現 5 是整型, 不能直接運算, 所以就找轉換建構函式test(int a),所以 r = t + 5 等價於 r = t + test(5) 所以可以順利編譯並且有輸出了
好了 說完了轉換建構函式 那麼問題來了:r = t + 5 t = 5;這些語句實際上使我們想寫的嗎 ,在我看來,這些語句在工程開發中是手誤,不應該存在的,為什麼,這是因為,這些語句是不會被編譯器認為是錯誤,程式在執行這些語句會得到我們意想不到的結果,是工程開發中很難發現的bug,我們在開發中實際上本意不是寫下這樣的**, 但是編譯沒有報錯,我們就很容易忽略了。
那麼怎麼解決? c++提供了解決辦法,那就是在轉換建構函式中宣告explicit關鍵字。explicit 關鍵字 就是杜絕編譯器進行隱式轉換,只能顯示轉換
待續。。。
C 轉換建構函式和轉換函式
1 轉換建構函式的作用 作用 將某種型別轉換為類型別 例如有下面的 base int a 轉換建構函式 base b 物件 b 12 解析 程式將使用建構函式base int a 構造出乙個臨時的無名base物件,並用12對其初始化。然後採用逐個成員賦值的方式將該臨時物件的內容賦值給物件b。這一過程...
剖析 移動建構函式
移動建構函式應用的場景?答 有時候我們會遇到這樣一種情況,我們用物件a初始化物件b,後物件a我們就不在使用了,但是物件a的空間還在呀 在析構之前 既然拷貝建構函式,實際上就是把a物件的內容複製乙份到b中,那麼為什麼我們不能直接使用a的空間呢?這樣就避免了新的空間的分配,大大降低了構造的成本。這就是移...
c 型別轉換建構函式
定義轉換建構函式的目的是實現型別的自動轉換。只有乙個引數,而且不是複製建構函式的建構函式,一般 就可以看作是轉換建構函式。當需要的時候,編譯系統會自動呼叫轉換建構函式,建立 乙個無名的臨時物件 或臨時變數 include using namespace std class complex compl...