推 QQ29:static_cast<T>(exp) 與傳統的 (T)exp 是相同的意思 12/28 22:48
→ QQ29:這句話 我之前我有波過文問過 結論似乎不是一樣的 12/28 22:49
→ QQ29:dynamic cast應該就是用來判定 安全下轉 機制 12/28 22:50
→ QQ29:其實我也很想知道這幾種 非用不可是哪邊... 12/28 22:50
推 oddguy:小弟在利用VC6環境開發的時候,嘗試用static_cast去轉換指 12/28 23:08
→ oddguy:標,但結果是編譯未能通過,像這樣:static_cast<int*>(p) 12/28 23:09
→ oddguy:而p本身是char*型。但改用(int*)p就可行。 12/28 23:10
→ oddguy:目前還不清楚是static_cast本身不支援這樣,還是VC6當中 12/28 23:11
→ oddguy:編譯器的特性 12/28 23:11
推 nowar100:int*轉成char*要用reinterpret_cast 12/28 23:12
→ oddguy:也有人說static_cast<T>應用來代替所有需要使用(T)的地方 12/28 23:13
推 UNARYvvv:static_cast 要指標型態對轉只能與 void * 做 12/28 23:13
推 oddguy:唔……小弟的疑問解決了 12/28 23:18
推 horngsh:loveme大大列的文章(MSDN)內講解的非常清楚... 01/06 12:41
> -------------------------------------------------------------------------- <
作者: nowar100 (拋磚引玉) 看板: C_and_CPP
標題: Re: [問題] C++幾種新式cast的用法
時間: Mon Dec 28 23:23:55 2009
分享一下我之前聽過的概念
C++設計這四種轉型,是為了防止PG做了不是自己想做的動作
例如通常會設成const,就是希望不要去動到他的值
但是這時候PG有這個必要性的時候,他就必須要用const_cast
這意義代表著PG必須自己清楚的了解,自己正在做"把const剝掉"這種危險事
static_cast是最普通的情況,基本上就是值互轉都是用這個
例如int轉char,int轉double等等
dynamic_cast是用於多型的時候,在run-time時決定是否可以真的這樣轉
例如將Based*轉成Derived*
const_cast是用於剝掉const屬性
例如const char*轉成char*
至於reinterpret_cast這東西很危險,通常也不太會用到
像是int*轉成char*,意義是"重新解析這個東西"
通常是在寫很底層,硬要用自己想要的觀點去存取資料結構,才會用到
至於void*是萬用型態,是個特例,所以可以用static_cast轉
至於C-style轉型,就是這四種的混合體,也就是暴力轉
C++故意將轉型分成四種,就是希望PG自己負起轉型的責任
PG使用不同的_cast的當下,必須清楚的知道自己在做什麼
也因此,通常C++的PG不應該去用C-style的轉型
※ 引述《james732 (好人超)》之銘言:
: 我想要請問一下,C++有四種新式的cast operator:
: static_cast, dynamic_cast, const_cast, reinterpret_cast
: 但我卻不知道這幾種 cast 的正確使用時機
: 目前對它們的認識僅有:
: static_cast<T>(exp) 與傳統的 (T)exp 是相同的意思
: 其他三種則負責傳統轉型無法做到的東西
: dynamic_cast<T>(exp) 與多型類別的轉換有關
: const_cast<T>(exp) 可以去除"const"這個特性,讓函式傳遞時能過關
: 我想它們被設計出來,應該會有些場合是「非用不可」的
: 但是卻試不出適合的例子
: 特別是 reinterpret_cast, 很多書都只說一句「與平台相依」
: 但是卻不懂它具體該怎麼使用...
: 因此想要請教一下,可否對於這幾種 cast 舉些「非用不可」的範例呢?
: 譬如說,在哪一種狀況裡,如果不使用 dynamic_cast 就一定會錯誤之類的
: 這幾個東西困擾了我好久,雖然沒學會好像也沒什麼關係 XD
: 但就覺得不太對勁...
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.113.235.154
※ 編輯: nowar100 來自: 140.113.235.154 (12/28 23:30)
推 VictorTom:推....:) 12/29 10:51
推 tyc5116:記得上次討論時有說到,除了static_cast以外,其餘的轉型 12/29 13:17
→ tyc5116:在使用時都要慎重考慮是否有其必要性 12/29 13:17
> -------------------------------------------------------------------------- <
作者: tinlans ( ) 看板: C_and_CPP
標題: Re: [問題] C++幾種新式cast的用法
時間: Tue Dec 29 06:21:29 2009
※ 引述《nowar100 (拋磚引玉)》之銘言:
: 分享一下我之前聽過的概念
: C++設計這四種轉型,是為了防止PG做了不是自己想做的動作
: 例如通常會設成const,就是希望不要去動到他的值
: 但是這時候PG有這個必要性的時候,他就必須要用const_cast
: 這意義代表著PG必須自己清楚的了解,自己正在做"把const剝掉"這種危險事
: static_cast是最普通的情況,基本上就是值互轉都是用這個
: 例如int轉char,int轉double等等
只要你有 100% 的把握,
向下轉型也是可以用這個,
典型的應用例子就是 Curiously Recurring Template Pattern (CRTP),
在這種狀況下不但可以大膽的用 static_cast 把 Base * 轉成 Dervied *,
還能省下 RTTI 機制造成的 overhead。
: dynamic_cast是用於多型的時候,在run-time時決定是否可以真的這樣轉
: 例如將Based*轉成Derived*
要再次強調的部分就是「用於多型的時候」,
C++ 根據多型性可以把 class 區分為 polymorphic class 跟 non-polymorphic class,
所謂的 polymorphic class 內必定至少要有一個 virtual function,
沒有 virtual function 的 class 就沒有對應的 virtual table,
沒有對應的 virtual table 就代表沒有對應的 type info 欄位,
也就是 RTTI 的所有機制在 non-polymorphic class 上無法作用。
以上面講的 CRTP 為例,
大部分使用 CRTP 的 Base 是不帶有 virtual function 的,
所以在這種狀況下寫 dynamic_cast<Dervied *>(ptrToBase) 會無法通過編譯,
這點很多初學 dynamic_cast 的人會看不懂錯誤訊息;
一般來說希望使用 dynamic_cast 等 RTTI 機制的話,
Base 至少就需要有一個 virtual function,
如果找不到的話那首選對象就是 virtual destructor。
STL 的 containers 都不具有 virtual function,
所以試圖以多型的方式使用它們就是不可能的,
dynamic_cast 當然也是無法作用,
所以 public 繼承 STL containers 一般來說可以視為觀念錯誤,
在 code 裡出現這種東西是一個很大的警訊。
: const_cast是用於剝掉const屬性
: 例如const char*轉成char*
用 const_cast 剝掉 const 雖然總是可以在 compile-time 運作,
但也是要小心,
這個前提是你必須 100% 確定你要轉的東西原本就不是 const,
否則 run-time 的行為不可預測,
compiler 可以把任何最初就是 const 的變數或物件安排在 read-only 區段,
對這種東西做 const_cast 再進行寫入可能會讓程式當掉,
當然也有一定的機率可以正常運作 (視平台和編譯環境而定);
合理的 const_cast 常出現在 operator overloading 的實作上,
讓 const 跟 non-const 的版本能 reuse 同一份 code。
: 至於reinterpret_cast這東西很危險,通常也不太會用到
: 像是int*轉成char*,意義是"重新解析這個東西"
: 通常是在寫很底層,硬要用自己想要的觀點去存取資料結構,才會用到
: 至於void*是萬用型態,是個特例,所以可以用static_cast轉
: 至於C-style轉型,就是這四種的混合體,也就是暴力轉
: C++故意將轉型分成四種,就是希望PG自己負起轉型的責任
: PG使用不同的_cast的當下,必須清楚的知道自己在做什麼
: 也因此,通常C++的PG不應該去用C-style的轉型
--
Ling-hua Tseng (uranus@tinlans.org)
Department of Computer Science, National Tsing-Hua University
Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design
Researching: Software pipelining for VLIW architectures
Homepage: https://www.tinlans.org
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.160.106.130
※ 編輯: tinlans 來自: 118.160.106.130 (12/29 06:26)
推 timTan:有機會把CRTP來個完整剖析嗎XD 12/29 07:23
推 VictorTom:也要推:) 12/29 10:45
推 oddguy:推CRTP的解釋 12/29 11:19
推 flashphp:先推專業! 但我對public 繼承 STL containers是錯誤觀念 12/29 11:38
→ flashphp:有點疑問, 子類別繼承STL container不是跟繼承int, char 12/29 11:40
→ flashphp:一樣自然嗎, 還是這是我生根的錯誤觀念 XD 12/29 11:42
推 nowar100:STL container沒有多型概念,容易memory leak 12/29 11:43
→ nowar100:通常會把它放為member 而不是去繼承他 12/29 11:43
推 flashphp:謝謝n大,另~能否舉例STL因繼承而造成memory leak的問題 12/29 12:34
→ nowar100:你用一個based*指向derived* based是STL derived是你自訂 12/29 14:41
→ nowar100:然後你去解構這個based* 他因為沒有多型 就leak了 12/29 14:41
推 legnaleurc:STL container 都沒有 virtual destructor ... 12/29 21:21
推 horngsh:推NOWAR大大的解釋...一針見血 01/06 12:49