c++四種新式轉型
通常用來將物件的常量性轉除,將const轉成non_const;
用來執行「安全向下轉型」通過父類訪問子類
很少用到,忽略
用來強迫隱式轉換,例如將non_const物件轉為const物件,或將int轉為double物件,也可以來執行上訴多種轉換的方向轉換,例如將void* 指標轉為typed指標,將base指標轉為derived指標,但無法將const轉為non_const,這個只有const_cast才能做到。
例如:class widget
;class derived : public base ;
derived d ;
base *pb = &d;
很多時候上述的兩個指標值並不相同,這種情況下會有個偏移量(offset)在執行期被施行於derived*指標身上,用已取得正確得base*指標值。上訴物件可能擁有乙個以上的位址(例如以base* 指向它的位址,和以derived指向它的位址。)
假設我們有個window base class 和乙個specialwindow derived class,兩者都定義了virtual 函式onresize。進一步假設special window 的onresize 函式被要求首先呼叫window的onresize。看起來是對的,但實際上錯的。
class window
public:
virtual void onresize()
class specialwindow : public window
public:
virtual void onresize()
static_cast(*this).onresize(); //derived onresize 實現**將*this轉型為window,然後呼叫其onresize;這是不可行的。
這一段程式將*this 轉型為window,對函式onresize的呼叫也因此呼叫了window::onresize.但恐怖你沒有想到,它呼叫的並不是當前物件上的函式,而是稍早轉型動作所建立的乙個「*this 物件之base class 成分」的暫時副本身上的onresize!,如果window::onresize修改了物件內容,當前物件其實沒被改變,改動的是副本。然而specialwindow::onresize內如果也修改物件,當前物件真的會被改動。
解決之道是拿掉轉型動作,代之以你真正想說話,你並不像哄騙編譯器將*this 視為乙個base class物件,你只是想呼叫base class版本的onresize函式,令他作用於當前物件身上。所以請這樣寫:
class specialwindow: public window
public :
virtual void onresize()
window::onresize();
之所以需要dynamic_cast,通常是因為你想在乙個你認定為derived class 物件身上執行derived class函式,但你的手上只有乙個「指向base」的指標或引用,你只能靠它們來處理物件。有兩個一般性做法可以避免這個問題。
class window;
class specialwindow:public window
public:
void blink();
typedef std::vector> vpw;
vpw winptrs;
for( vpw::iterator iter = winptrs.begin();iter != winptr.end(); ++iter)
if(specialwindow * psw =dynamic_cast(iter->get()))
psw->blink();
typedef std::vector> vpsw;
vpsw winptrs;
for( vpsw::iterator iter = winptrs.begin(); iter != winptrs.end();++iter)
(*iter)->blink();
class window
//預設實現**可能是個餿主意
class specialwindow :public window
public :
virtual void blink() ;
typedef std::vector> vpw;
vpw winptrs;
for(vpw::iterator iter = winptrs.begin();iter != winptrs.end(); ++iter)
(*iter)->blink();
1.如果可以,盡量避免轉型,特別是注重效率的**中避免dynamic_cast。如果有個設計需要轉型動作,試著發張無需轉型的代替設計,
2.如果轉型是必要的,試著將他隱藏於某個函式背後,客戶隨後可以呼叫該函式,而不需要將轉型放進他們自己的**內。
3.寧可使用c++style(新轉型),也不要使用就是轉型。前者很容易辨識出。
條款27 盡量少做轉型動作
c 中的轉型語法包括舊式轉型和新式轉型。舊式轉換包括 t expression 將expression轉型為t,c風格的轉型動作 t expression 將expression轉型為t,函式風格的轉型動作 新式轉型包括 const cast expression const cast通常被用來將物...
條款27 盡量少做轉型動作
c 的設計目標之一是保證 型別錯誤 絕不會發生。但轉型 cast 破壞了型別系統 type system 舊式轉型,c風格的轉型動作,如下 t tmp 將tmp轉型為t t tmp 同上,函式風格的轉型動作 c 提供四種新式轉型 new style或c style casts 1 const cas...
條款27 盡量少做轉型動作
在談及顯式轉換之前,先簡單說說隱式轉換。int ival 0 ival 3.541 3 doubl向int轉換會丟失精度,編譯器會警告 從double到int轉換可能會丟失資料,結果ival等於6整數3被轉換為double型別,然後執行浮點型別加法操作,得double型別結果6.541,然後將dou...