唉唉
話說上次考完趨勢的線上測驗之後,今天收到面試通知了
不過是QA的缺就是了,RD可能標準比較高吧=ˇ=
雖然也不排斥QA,不過我對QA真的是一無所知...
聽說會考一堆Linux的指令和網路相關的問題,對於只會寫code的我來說,看來又是一次要被洗臉的面試XD
然後隔天又要去另一間外商進行英文面試...
我表示心情很複雜=ˇ=
不過要準備一下英文面試,雖然只剩三天了
雖然有準備也大概是從0到0.001的這種程度(滿分大概是100),還是來準備下吧
今天來看看C++裡面的轉型好了
在C裡面有所謂的強制轉型,就是前面有個括弧,像什麼(int)這種,就可以直接轉型了
但C++因為有了繼承和多型這種概念,所以也多引入了一點轉型的東西
這些大多是因為強制轉型會有一些問題所以才引入的
在C++的轉型裡面,又分為隱式轉型和顯示轉型
所謂隱式轉型就是指編譯器偷偷幫你轉型,可能只會跳warning給你看,不會是error
一般來說如果需要進行比較複雜的轉型或是不想看到warning,都會使用顯示轉型
也就是告訴編譯器直接轉就好,你不用管我,後果我自己負責
另外要強調一下,其實沒事就不要去做轉型這種事
秀操作通常都沒什麼好下場的...
以下就來介紹幾個常見的轉型方式,主要參考底下這些連結:
http://windsplife.blogspot.com/2010/09/cstaticcast-dynamiccast-reinterpretcast.html
http://ot-note.logdown.com/posts/173174/note-cpp-named-type-convertion
1. const_cast <type-id>( expression )
這個就是把const、violate、mutable這些type轉成一般的type
但... 說實在我不太知道這東西是在什麼情境下才會使用
一般有加上前面修飾字的變數就是為了要滿足某些條件才加的
比如說const就是表示不允許去改動他,那就沒道理你又想要去改動他了...
所以就... 參考一下就好,沒事不會用到XD
2. reinterpret_cast < type-id >( expression )
這是一個用於指標的轉換,比如說今天是一個指向int的指標,你硬要把他轉成char的
就可以用reinterpret_cast,但因為底層的資料內容是不會變的
所以如果之後轉回來的話,是可以保證資料不會遺失的
但有一個缺點就是... 因為是指標的轉型,也就是指向位址的操作
可能會因為編譯器不一樣導致執行出的結果有所差異
所以在我看來... 除非真的有必要... 也是一個不太建議的做法
這種做法是不存在可攜性的,而且具有危險性,就是難以預期他的行為
3. static_cast < type - id > (expression)
這個就是常見的東西了,一般常見的型態轉換就是靠這個,大概又可以分成幾種轉型
a. 算術轉型:
就是int轉float,float轉double,或是unsigned轉為signed
基本上就是要保留一些資訊的轉型,比如說小數點或負數
b. void*指標轉型:
因為void*是一個萬用指標,所以可以用static_cast轉來轉去,(注意其他指標只能用reinterpret_cast)
比如說以下的例子:
// main.cpp
Dog dog;
DoMeow(&dog); // 傳一個 Dog* 進入 void*, 編譯器不會叫
// cat.h
void DoMeow(void *vp){ // 傳入的 Dog* 被隱性轉成 void*
Cat* cat = static_cast<Cat*>(vp); // void* 的 (Dog 物件) 被轉成 Cat*
cat->meow(); // GG here, Dog cannot meow
}
其實這是個滿方便的功能,但在轉回來的時候可能沒有辦法保障轉回來後是正確的
所以還是要謹慎使用XD
c. class型態轉換:
class之間也可以用static_cast轉換,只是要滿足一些特殊條件
比如說以下這個例子:
// meow.h
class Cat{};
class Lion{Lion(Cat& cat){};};
// main.cpp
Cat cat;
Lion lion = static_cast<Lion>(cat); // ok
Lion lion2 = cat; // ok
在lion的建構子裡面有一個cat的參數,所以在assign operator的時候就會把cat當作參數去建構lion
這個就是C++裡面的隱式轉換,如果不想要讓編譯器這樣幫你處理的話
就必須在建構子前加上explict關鍵字
另外也可以利用修改operator T()的方式... 但我覺得class間的轉型還是用dynamic_cast比較安全
4. dynamic_cast < type-id > ( expression )
這是最後一種了,個人覺得對於C++來說這是最實用的一種
使用的情境必須在:
a. class至少要有一個virtual function
b. 若型別不符,會回傳 0 表示,來讓程式員判斷例外的程序
c. 會動用到 RTTI 而產生一筆查尋的 overhead,來當做是型別安全的 tradeoff
所以說對於多型的狀況,理論上應該都要用這個才對
只要是非底層或是對執行速度沒那麼要求的class都建議使用
而且他是在執行期去檢查是否有問題,有問題就會直接回傳0
但因為是額外的檢查,執行上會多花一點時間
RTTI(Runtime type information)這個東西一般是放在virtual table裡面的,所以說class至少要有一個virtual function,才會建出virtual table
不過一般來說解構子都會是virtual function(不是的話可能會有memory leak的問題)
如果是在寫C++,C的那種強制轉型建議少用吧
因為在使用強制轉型的同時,其實也只是在從上面的轉型方式裡一個個去嘗試而已
對於不知道的行為,還是盡量避免比較好
那這篇就這樣了
可能有些地方沒有講得很清楚,要看的話還是去參考前面參考的連結吧
下一篇再見~~
留言列表