條款27 盡量少做轉型動作

2021-10-11 17:57:02 字數 2449 閱讀 9149

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...