簡體   English   中英

隱式 VS 顯式轉換

[英]Implicit VS Explicit Conversion

Nicolai M. Josuttis 的 C++ 標准庫指出:

之間有細微差別

X x;
Y y(x) //explicit conversion

X x;
Y y = x; //implicit conversion

接下來說:“前者通過使用 X 類型的顯式轉換創建一個 Y 類型的新 object,而后者通過使用隱式轉換創建一個 Y 類型的新 object。

我猜我對顯式轉換和隱式轉換的概念有點困惑。 在這兩種情況下,您都使用 X 並將其推入 Y 本身 - 一種使用 Y 的構造函數,另一種使用賦值運算符。

在這兩種情況下如何處理轉換有什么區別,是什么使它顯式/隱式,以及這如何與使用“顯式”關鍵字定義的 class 構造函數聯系起來,如果有的話?

一個使用 Y 的構造函數,一個使用賦值運算符。

沒有。 在第二種情況下,它不是賦值,而是初始化,賦值運算符( operator= )永遠不會被調用; 相反,調用了一個非explicit的單參數構造函數(接受類型X作為參數)。

初始化和賦值之間的區別很重要:在第一種情況下,正在創建一個新的 object,它以初始化時使用的值開始其生命(因此調用構造函數),而賦值發生在 object被分配(~復制)給一個 object已經存在並且已經在一個明確的 state 中

無論如何,您編寫的兩個初始化 forms 不同之處在於,在第一種情況下,您顯式調用構造函數,因此任何構造函數都是可以接受的; 在第二種情況下,您正在隱式調用構造函數,因為您使用的不是“經典”構造函數語法,而是初始化語法。

在這種情況下,只有未標記為explicit的單參數構造函數是可接受的。 這樣的構造函數被某些人稱為“轉換”構造函數,因為它們涉及隱式轉換。

this other answer中所指定,任何未標記為explicit的構造函數都可以參與隱式轉換,例如將傳遞給 function 的 object 轉換為此類 ZC1C425268E68385D1AB5074C17A94F 所期望的類型。 實際上,您可能會說這就是第二個示例中發生的情況:您想用x初始化(=使用從其他地方復制的值創建) y ,但首先必須將x轉換為類型Y ,這是通過隱式構造函數完成的.

這種隱式轉換通常是可取的:例如考慮一個字符串 class ,它具有來自const char *的轉換(即非explicit )構造函數:任何接收string參數的 function 也可以用“普通”C調用-string:由於調用者將使用 C 字符串的轉換構造函數,被調用者將收到其string object。

盡管如此,在某些情況下,單參數構造函數可能不適合轉換:通常會發生這種情況,因為它們的唯一參數沒有在概念上“轉換”為正在創建的 object 的類型,但它只是構造的一個參數; 例如考慮一個文件 stream object:可能它會有一個接受要打開的文件名的構造函數,但是說這樣的字符串被“轉換”為適用於該文件的 ZF7B44CFAFD5C52223D5498E7B 是沒有意義的。

您還可以找到一些更復雜的場景,在這些場景中,這些隱式轉換可能會完全打亂程序員對重載解析所期望的行為; 這方面的例子可以在我上面鏈接的答案下面的答案中找到。

更簡單地說,也可能發生某些構造函數可能非常重量級,因此 class 設計者可能希望確保顯式調用它們。 在這些情況下,構造函數被標記為explicit ,因此它只能在“顯式作為構造函數”調用時使用,並且不參與隱式轉換。

第一種形式是直接初始化 二是拷貝初始化

復制初始化隱式調用轉換構造函數或轉換運算符,然后顯式調用復制構造函數(可以省略復制構造函數調用,但仍必須執行可訪問性檢查)。

考慮第三種可能性,即復制初始化,但轉換是顯式的:

Y y = Y(x);

或者

Y y = (Y)x;

一個使用賦值運算符

不,不是的。 它直接調用構造函數。

一個是顯式的,一個是隱式的的原因是,當您不希望它們發生時,可能會發生隱式轉換。 明確的不能。 最簡單的例子是 bool。

假設您發明了某種可以為真或假的類型,例如指針。 然后讓我們進一步說,您決定為了讓用戶的生活更輕松,您讓它隱式轉換為 bool。 這很好——直到你的一個用戶做了一些愚蠢的事情。

int i = 0;
i = i >> MyUDT();

哦等等 - 為什么它甚至可以編譯? 您根本無法轉移 MyUDT! 它可以編譯,因為bool是一個整數類型。 編譯器將其隱式轉換為布爾值,然后轉換為可以移動的東西。 上面的代碼非常愚蠢——我們只希望人們能夠轉換為bool ,而不是 bool 以及 bool 可能想要做的任何其他事情。

這就是為什么將顯式轉換運算符添加到 C++0x 的原因。

隱式轉換不需要任何轉換運算符。 當將數據從較小的整數類型轉換為較大的類型或派生類型到基類型時,通常會使用此轉換。

詮釋 iVal = 100; 雙 dVal = iVal;

顯式轉換構造函數優於隱式轉換運算符,因為在后一種情況下,需要額外調用復制構造函數。 隱式和顯式轉換

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM