C++類型轉(zhuǎn)換


隱式類型轉(zhuǎn)換:

C++的隱式轉(zhuǎn)換發(fā)生在以下四種情況:

  • 在混合類型的算術(shù)表達(dá)式中哩盲。
  • 在表達(dá)式賦值中挨摸。
  • 表達(dá)式傳給函數(shù)時镇饮,實(shí)參轉(zhuǎn)換為形參的類型广鳍。
  • 函數(shù)返回表達(dá)式時轉(zhuǎn)換成返回值類型。

顯式類型轉(zhuǎn)換:

  • 被稱為“強(qiáng)制類型轉(zhuǎn)換”(cast)
  • C風(fēng)格:(type-id)
  • C++風(fēng)格:static_cast蝶溶、dynamic_cast嗜历、reinterpret_cast、和const_cast

1. static_cast

  • 用法:static_cast < type-id > ( expression )
  • 通常用于轉(zhuǎn)換數(shù)值類型抖所,進(jìn)行非多態(tài)的類型轉(zhuǎn)換梨州。
  • 在轉(zhuǎn)換時不進(jìn)行類型檢查,在編譯時進(jìn)行類型檢查田轧,如果轉(zhuǎn)換不成功則編譯錯誤暴匠,因此不安全。
// static_cast_Operator.cpp
// compile with: /LD
class B {};

class D : public B {};

void f(B* pb, D* pd) {
   D* pd2 = static_cast<D*>(pb);   // Down
                                   // Not safe, D can have fields
                                   // and methods that are not in B.

   B* pb2 = static_cast<B*>(pd);   // Up
                                   // Safe conversion, D always contains all of B.
}
  • 與 dynamic_cast 不同傻粘,pb 的 static_cast 轉(zhuǎn)換不執(zhí)行運(yùn)行時檢查每窖。 由 pb 指向的對象可能不是 D 類型的對象,在這種情況下使用 *pd2 會是災(zāi)難性的弦悉。 例如窒典,調(diào)用 D 類(而非 B 類)的成員函數(shù)可能會導(dǎo)致訪問沖突。

2. dynamic_cast

  • 用法:dynamic_cast < type-id > ( expression )
  • 用于指針和引用稽莉。不同類型的指針和引用之間的轉(zhuǎn)換瀑志。
  • 注意dynamic_cast在幫助你瀏覽繼承層次上是有限制的。它不能被用于缺乏虛函數(shù)的類型上污秆。也即如果想將基類指針轉(zhuǎn)換為派生類指針劈猪,如果基類不是虛類則無法實(shí)現(xiàn)
  • 被用于安全地沿著類的繼承關(guān)系向下進(jìn)行類型轉(zhuǎn)換良拼。這就是說战得,你能用dynamic_cast把指向基類的指針或引用轉(zhuǎn)換成指向其派生類或其兄弟類的指針或引用,而且你能知道轉(zhuǎn)換是否成功将饺。
  • 向上轉(zhuǎn)換和static_cast作用一樣贡避。不要求虛基類痛黎。
  • 支持同一個基類的不同派生類指針之間的轉(zhuǎn)換予弧。而static_cast則會報錯刮吧。
  • 失敗的轉(zhuǎn)換將返回空指針(當(dāng)對指針進(jìn)行類型轉(zhuǎn)換時)或者拋出異常(當(dāng)對引用進(jìn)行類型轉(zhuǎn)換時)。例子如下掖蛤。
// static_cast_Operator_2.cpp
// compile with: /LD /GR
class B {
public:
   virtual void Test(){}
};
class D : public B {};

void f(B* pb) {
   D* pd1 = dynamic_cast<D*>(pb);
   D* pd2 = static_cast<D*>(pb);
}
  • 如果 pb 確實(shí)指向 D 類型的對象杀捻,則 pd1pd2 將獲取相同的值。 如果 pb == 0蚓庭,它們也將獲取相同的值致讥。
  • 如果 pb 指向 B 類型的對象,而非指向完整的 D 類器赞,則 dynamic_cast 足以判斷返回零垢袱。 但是,static_cast 依賴于程序員的斷言港柜,即 pb 指向 D 類型的對象请契,因而只是返回指向那個假定的 D 對象的指針。

3. reinpreter_cast

  • 用法:reinpreter_cast<type-id> (expression)
  • type-id必須是一個指針夏醉、引用爽锥、算術(shù)類型、函數(shù)指針或者成員指針畔柔。
  • 它可以把一個指針轉(zhuǎn)換成一個整數(shù)氯夷,也可以把一個整數(shù)轉(zhuǎn)換成一個指針(先把一個指針轉(zhuǎn)換成一個整數(shù),在把該整數(shù)轉(zhuǎn)換成原類型的指針靶擦,還可以得到原先的指針值)腮考。
  • 比較底層的轉(zhuǎn)換,在非相關(guān)的類型之間轉(zhuǎn)換玄捕。操作結(jié)果只是簡單的從一個指針到別的指針的值的二進(jìn)制拷貝秸仙。在類型之間指向的內(nèi)容不做任何類型的檢查和轉(zhuǎn)換。reinpreter_cast是特意用于底層的強(qiáng)制轉(zhuǎn)型桩盲,導(dǎo)致實(shí)現(xiàn)依賴(就是說寂纪,不可移植)的結(jié)果。

4. const_cast

  • 用法:const_cast<type_id> (expression)
  • 該運(yùn)算符用來修改類型的constvolatile屬性赌结。除了constvolatile修飾之外捞蛋, type_idexpression的類型是一樣的。
  • 常量指針被轉(zhuǎn)化成非常量指針柬姚,并且仍然指向原來的對象拟杉;常量引用被轉(zhuǎn)換成非常量引用,并且仍然指向原來的對象量承;常量對象被轉(zhuǎn)換成非常量對象搬设。

關(guān)于多態(tài)的類指針轉(zhuǎn)換

  • 向上轉(zhuǎn)換:派生類指針轉(zhuǎn)為基類指針穴店。
  • 向下轉(zhuǎn)換:基類指針轉(zhuǎn)換為派生類指針。

見下面這個例子:

class A {
 public:
   A() {
     a = 0;
   }
 private:
   int a;
};

class B : public A {
 public:
   B() {
     b = 0;
   }
 private:
   int b;
};
int main() {
  A *pa1, *pa2, *pa3, *pa4;
  B *pb1, *pb2, *pb3;

  A a1;
  pa1 = &a1;
  B b1;
  pb1 = &b1;
  
  // 首先拿穴,對于指針直接指向?qū)ο螅?  pa2 = &b1;  // Correct 指針pa直接指向B中A有的一部分
  pb2 = &a1;  // Error 需要進(jìn)行強(qiáng)制類型轉(zhuǎn)換來縮小pb指針的范圍
              // error: invalid conversion from 'A*' to 'B*'

  // 指針之間的轉(zhuǎn)換
  pa3 = dynamic_cast<A*>(pb3);  // Up Correct 見上泣洞,使得指針能夠正常工作
  pb3 = dynamic_cast<B*>(pa4);  // Down Error
  // error: cannot dynamic_cast 'pa4' (of type 'class A*') to type 'class B*' (source type is not polymorphic)
  // 由于類A不是虛基類,不能將其指針pa轉(zhuǎn)換為類B的指針默色,因?yàn)轭怋的指針能夠?qū)中沒有的內(nèi)容進(jìn)行操作球凰,直接轉(zhuǎn)換則不能做到。若A為虛基類腿宰,B是對A中方法的重寫呕诉,則能夠正確轉(zhuǎn)換

  return 0;
}

例子:

  • 此轉(zhuǎn)換類型稱為“向上轉(zhuǎn)換”,因?yàn)樗鼘⒃陬悓哟谓Y(jié)構(gòu)上的指針吃度,從派生的類移到該類派生的類甩挫。 向上轉(zhuǎn)換是一種隱式轉(zhuǎn)換。
class B { };
class C : public B { };
class D : public C { };

void f(D* pd) {
   C* pc = dynamic_cast<C*>(pd);   // ok: C is a direct base class
                                   // pc points to C subobject of pd 
   B* pb = dynamic_cast<B*>(pd);   // ok: B is an indirect base class
                                   // pb points to B subobject of pd
}
  • 此轉(zhuǎn)換類型稱為“向下轉(zhuǎn)換”椿每,因?yàn)樗鼘⒃陬悓哟谓Y(jié)構(gòu)下的指針伊者,從給定的類移到該類派生的類。
class B {virtual void f();};
class D : public B {virtual void f();};

void f() {
   B* pb = new D;   // unclear but ok
   B* pb2 = new B;

   D* pd = dynamic_cast<D*>(pb);   // ok: pb actually points to a D
   D* pd2 = dynamic_cast<D*>(pb2);   // pb2 points to a B not a D
}

參考閱讀

static_cast, dynamic_cast, const_cast探討
static_cast 運(yùn)算符
dynamic_cast 運(yùn)算符

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拖刃,一起剝皮案震驚了整個濱河市删壮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兑牡,老刑警劉巖央碟,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異均函,居然都是意外死亡亿虽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進(jìn)店門苞也,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洛勉,“玉大人,你說我怎么就攤上這事如迟∈蘸粒” “怎么了?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵殷勘,是天一觀的道長此再。 經(jīng)常有香客問我,道長玲销,這世上最難降的妖魔是什么输拇? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮贤斜,結(jié)果婚禮上策吠,老公的妹妹穿的比我還像新娘逛裤。我一直安慰自己,他們只是感情好猴抹,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布带族。 她就那樣靜靜地躺著,像睡著了一般洽糟。 火紅的嫁衣襯著肌膚如雪炉菲。 梳的紋絲不亂的頭發(fā)上堕战,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天坤溃,我揣著相機(jī)與錄音,去河邊找鬼嘱丢。 笑死薪介,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的越驻。 我是一名探鬼主播汁政,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缀旁!你這毒婦竟也來了记劈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤并巍,失蹤者是張志新(化名)和其女友劉穎目木,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懊渡,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刽射,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了剃执。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片誓禁。...
    茶點(diǎn)故事閱讀 38,637評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖肾档,靈堂內(nèi)的尸體忽然破棺而出摹恰,到底是詐尸還是另有隱情,我是刑警寧澤怒见,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布俗慈,位于F島的核電站,受9級特大地震影響速种,放射性物質(zhì)發(fā)生泄漏姜盈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一配阵、第九天 我趴在偏房一處隱蔽的房頂上張望馏颂。 院中可真熱鬧示血,春花似錦、人聲如沸救拉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亿絮。三九已至告喊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間派昧,已是汗流浹背黔姜。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蒂萎,地道東北人秆吵。 一個月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像五慈,于是被迫代替她去往敵國和親纳寂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評論 2 348

推薦閱讀更多精彩內(nèi)容

  • C++類型轉(zhuǎn)換總結(jié) 本章內(nèi)容:1 前言2 static_cast3 dynamic_cast4 const_cas...
    Haley_2013閱讀 949評論 0 50
  • C++添加了四種類型轉(zhuǎn)換運(yùn)算符: 其中type-name表示轉(zhuǎn)換后的類型泻拦,expresion表示被轉(zhuǎn)換的表達(dá)式毙芜。 ...
    Tianql閱讀 338評論 0 0
  • 這篇介紹C++的4種類型轉(zhuǎn)換 dynamic_cast, static_cast, reinterpret_cas...
    CodingCode閱讀 496評論 0 0
  • static_cast 用于類層次結(jié)構(gòu)中,基類和子類之間指針和引用的轉(zhuǎn)換争拐。進(jìn)行上行轉(zhuǎn)換腋粥,也就是把子類的指針或引用轉(zhuǎn)...
    第八區(qū)閱讀 472評論 0 0
  • C++ 一共有4種類型轉(zhuǎn)換方式,分別是: static_cast陆错,dynamic_cast灯抛,const_cast,...
    wayyyy閱讀 432評論 0 0