2011-09-30 69 views
11

在閱讀教材中的內容後,我有點困惑。關於代碼:這是鑄造還是建築?

void doSomeWork(const Widget& w) 
{ 
    //Fun stuff. 
} 

doSomeWork(Widget(15)); 

doSomeWork()需要const Widget&參數。教科書Effective C++ III指出這會創建一個臨時Widget對象傳遞給doSomeWork。它說,這可以被替換爲:

doSomeWork(static_cast<Widget>(15)); 

爲兩個版本的石膏 - 第一僅僅是一個函數,C風格六名演員。我會認爲Widget(15)會調用一個構造函數來獲取一個整數參數。

在這種情況下執行構造函數嗎?

回答

12

在C++中,這種表達式鑄型的一種形式,至少在語法上。即您使用C++函數強制轉換語法Widget(15)來創建Widget類型的臨時對象。

即使你使用多參數的構造函數(如Widget(1, 2, 3))它仍然被認爲功能鑄符號的變化建立一個臨時的(參見5.2.3節)

換句話說,你的「是這個演員或建築「這個問題是錯誤的,因爲它意味着演員和」建築「之間的相互排斥。它們不是相互排斥的。實際上,每種類型轉換(是一種明確的轉換或更隱含的東西)只不過是目標類型的新臨時對象(可能不包括某些引用初始化)的創建(「構造」)。

順便說一句,功能強制符號是主要的C++符號。 C語言沒有功能風格的演員表。

1

你說:

第一僅僅是一個函數,C風格鑄顯然

第一不會編譯用C,這不是C風格。 C型看起來像(Widget)15。在這裏,使用Widget::Widget(int)創建臨時對象。

因此,它不是C風格的演員。

+1

@Constantinius:究竟是什麼錯誤? – AnT

+0

我編輯了你的答案。 – 2011-09-30 15:11:27

-1

Yeeeah。你可以用

static_cast<Widget>(15) 

更換

Widget(15) 

因爲它會被編譯器替換回:d

當你施放intWidget編譯器查找Widget::Widget(int);,並將其放置在那裏。

5

短:是的。

長:

您可以自己始終測試的那些東西,這樣做例如: -

#include <iostream> 

struct W 
{ 
    W(int i) 
    { 
     std::cout << "W(" << i << ")\n"; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    W w(1); 
    W(2); 
    static_cast<W>(3); 
} 

其輸出

W(1) 
W(2) 
W(3) 
+0

第一個不是演員。你試圖展示什麼? – MSalters

+2

@ MSalters:對於大多數類型而言,強制轉換與創建(臨時)對象沒有區別。 – PlasmaHH

+1

@ MSalters:我認爲他試圖展現這種差異 – 2011-09-30 14:59:00

3

是,它既是:)。演員陣容是一個句法結構(即你輸入的東西)。在這種情況下,作爲演員的結果調用構造函數。就像一個構造函數被調用爲輸入

Widget w(15); 
3

兩個Widget(15)static_cast<Widget>(15)的結果是鑄件,或轉換 運營商,如果你喜歡。通過將15轉換爲Widget,兩者都創建指定的 類型的新對象。由於15沒有任何 轉換運算符,因此執行此轉換的唯一方法是通過 分配必要的內存(在堆棧上)並調用適當的構造函數 。這實在是沒有什麼不同的是double(15)static_cast<double>(15),除了我們通常不認爲 double爲具有構造函數(但由此double是一個新的 對象,從15不同,其類型爲int)。

0

是的,當然。任何只有一個參數的構造函數都將被視爲CONVERSION CONSTRUCTOR。您的構造函數已經採用了一個參數int,以便編譯器可以「隱式」調用此構造函數以匹配參數(值爲15,即int)。

有一個簡單的技巧來防止這種錯誤,只需在構造函數之前使用關鍵字explicit即可。

檢查this瞭解更多信息。