2013-12-10 64 views
-1

據我所知,(MyType)foo,MyType(foo)static_cast<MyType>(foo)有些類似,前兩個成爲最後一個(編輯:我已經被糾正了,前面的句子是不真實的。)我的問題是哪個是慣用的版本?情境是一個考慮因素?哪種文件static_cast的慣用方式?

因爲我知道C風格轉換在C++中不是首選,所以它可以轉換爲功能轉換和static_cast。

+0

http://stackoverflow.com/questions/103512/in-c-why-use-static-castintx-instead-of-intx – aardvarkk

+5

不,這些*不*相同。例如,第一個變爲'reinterpret_cast',而不是'static_cast'。 – dasblinkenlight

+4

事實上,你可以grep'static_cast'使它成爲我眼中的贏家。 – molbdnilo

回答

2

前兩個,(MyType)fooMyType(foo),具有相同的含義。含義是什麼取決於MyTypefoo的類型。因此,例如:

((int)1.0); // a static_cast 
int i = 0; 
((char*)&i); // a reinterpret_cast 
const int j = 0; 
((int*)&j); // a const_cast 
((char*)&j); // a combination of a const_cast and a reinterpret_cast 

typedef char *CharPtr; 
CharPtr(&j); // a C-style cast, same as ((CharPtr)&j) or ((char*)&j) 

所以C風格的強制類型轉換不理想的原因是,C-風格轉換做很多不同的事情。C++提供了區分它們的手段。在許多情況下,可以更容易地理解代碼,尤其是一旦您使用C++編寫泛型代碼,並且類型不如C中典型代碼明顯。

這就是爲什麼static_cast等在C++中首選 - 他們明確地爲讀者提供了一些本來難以爲自己解決的問題。順便說一句,static_cast也會做一些不同的事情,所以原則上你可能會想要更多不同的演員。但是static_cast至少比C風格演員少。

具有一個參數的功能風格演員陣容是 C型演員陣容。在所有情況下,它們在標準中明確定義爲完全相同的意思。

現在,在某些情況下,如果使用C語言語法編寫函數語法,而不是使用C語言編寫語法,則可能會接受C風格轉換。這通常是目標類型是類的時候,並且很明顯哪個構造函數會被調用。在這種情況下,std::vector<int>(0)static_cast<std::vector<int>>(0)更短,並且通常更清晰,因爲它可以作爲構造函數調用讀取。但它仍然具有與編寫(std::vector<int>)0相同的「危險」。如果您要以這種方式編寫每次轉換,那麼最終您會不小心從指針類型中刪除const

3

在我的書中使用明確的轉換是慣用的。

static_cast<MyType>(foo)優於(MyType)foo,因爲它更具表現力和明確性。這在很多情況下特別有用,其中 不是意味着您期望它的意思。例如,在您的示例中,這些情況可能完全不會減少到static_cast,而是reinterpret_cast

在代碼審查中,我會拒絕所有非算術類型的C風格類型轉換。

+0

我會允許他們算術類型。我不認爲'std :: tolower(static_cast (c));'比'std :: tolower((unsigned char)c);'更好。目標類型足以確保它不能刪除const或其他可怕的東西。但是如果你需要一個非常簡單的規則,那麼它必須是禁止它們的。 IIRC還有一些愚蠢的事情,只能用C風格的演員才能完成,但在幾乎所有情況下,你都無所事事。將指針投射到指向私人基地的指針或其他東西。 –

+0

@SteveJessop:我並沒有真正想到算術類型。我想我多少會同意你的看法。在這種意義上說,'i'的類型未來可能會發生變化,但這似乎有點奇怪。 –

+0

@SteveJessop:對。 –

2

首先,雖然新的C++,功能風格演員 C風格演員。他們做同樣的事情。

C型表演首先嚐試到static_cast,如果這不起作用,請執行reinterpret_cast 。這很糟糕,因爲旨在進行簡單更改的操作可能會變得非常奇怪。

舉一個例子,假設你有一個Foo* f和一個完全不相關的類Bar。您可以(Bar*)f,它會默默重新解釋*fBar,可能導致未定義的行爲。

如果FooBar是相關類型,A static_cast只適用於此情況。

現在,即使static_cast可能太強大了,所以我經常寫一個implicit_castnon_cast模板,它可以轉換而不需要轉換。同樣,我寫as_const,它增加const而不是要求const_cast(它既可以添加也可以刪除const,並且刪除const比添加它更危險)。

這是有點惱人的,有在C++中沒有明確的安全投了,我不知道如何寫一個(一個將執行explicit構造函數,但不會投「向下」類型層次結構像static_cast會)。


這是一個過於簡單化,但足夠接近真實。

+0

「在C++中沒有明確的安全轉換」 - 嗯。在兩個模板參數都是指針類型和(在remove_pointer之後)源是目標的基礎的情況下,執行'static_cast'並禁用的模板函數? –

+0

@SteveJessop「向上」指針轉換也是安全的,所以雅。 SFINAE可能會工作。這是否抓住每一個案例? – Yakk

+0

順便說一句,「C++ explicit_cast」的網頁搜索引導我在那裏:http://stackoverflow.com/questions/5693432/making-auto-cast-safe(簡而言之,C++ 11統一初始化和'std :: is_constructible '被喚起) –