close

唉唉

話說上次考完趨勢的線上測驗之後,今天收到面試通知了

不過是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的那種強制轉型建議少用吧

因為在使用強制轉型的同時,其實也只是在從上面的轉型方式裡一個個去嘗試而已

對於不知道的行為,還是盡量避免比較好

 

那這篇就這樣了

可能有些地方沒有講得很清楚,要看的話還是去參考前面參考的連結吧

下一篇再見~~

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 頁頁頁六滴 的頭像
    頁頁頁六滴

    人森很精彩,所以要把所有事情都記起來=ˇ=

    頁頁頁六滴 發表在 痞客邦 留言(0) 人氣()