亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

深入解析C++中的動態類型轉換與靜態類型轉換運算符

2020-05-23 14:11:07
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了C++中的動態類型轉換與靜態類型轉換運算符,即dynamic_cast與static_cast的用法,需要的朋友可以參考下
 

dynamic_cast 運算符
將操作數 expression 轉換成類型為type-id 的對象。
語法

dynamic_cast < type-id > ( expression )

備注
type-id 必須是一個指針或引用到以前已定義的類類型的引用或“指向 void 的指針”。如果 type-id 是指針,則expression 的類型必須是指針,如果 type-id 是引用,則為左值。
有關靜態和動態強制轉換之間區別的描述,以及各在什么情況下適合使用,請參見 static_cast。
在托管代碼中的 dynamic_cast的行為中有兩個重大更改。
為指針的dynamic_cast 對指向裝箱的枚舉的基礎類型的指針將在運行時失敗,則返回 0 而不是已轉換的指針。
dynamic_cast 將不再引發一個異常,當 type-id 是指向值類型的內部指針,則轉換在運行時失敗。該轉換將返回 0 指示運行值而不是引發。
如果 type-id 是指向 expression的明確的可訪問的直接或間接基類的指針,則結果是指向 type-id 類型的唯一子對象的指針。例如:

// dynamic_cast_1.cpp// compile with: /cclass 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}

此轉換類型稱為“向上轉換”,因為它將在類層次結構上的指針,從派生的類移到該類派生的類。向上轉換是一種隱式轉換。
如果 type-id 為 void*,則做運行時進行檢查確定 expression的實際類型。結果是指向 by expression 的完整的對象的指針。例如:

// dynamic_cast_2.cpp// compile with: /c /GRclass A {virtual void f();};class B {virtual void f();};void f() {  A* pa = new A;  B* pb = new B;  void* pv = dynamic_cast<void*>(pa);  // pv now points to an object of type A  pv = dynamic_cast<void*>(pb);  // pv now points to an object of type B}

如果 type-id 不是 void*,則做運行時進行檢查以確定是否由 expression 指向的對象可以轉換為由 type-id指向的類型。
如果 expression 類型是 type-id類型的基類,則做運行時檢查來看是否 expression 確實指向 type-id類型的完整對象。如果為 true,則結果是指向 type-id類型的完整對象的指針。例如:

// dynamic_cast_3.cpp// compile with: /c /GRclass 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}

此轉換類型稱為“向下轉換”,因為它將在類層次結構下的指針,從給定的類移到該類派生的類。
對于多重繼承,引入多義性的可能性??紤]下圖中顯示的類層次結構。
對于 CLR 類型,如果轉換可以隱式執行,則 dynamic_cast 結果為 no-op,如果轉換失敗,則 MSIL isinst 指令將執行動態檢查并返回 nullptr。
以下示例使用 dynamic_cast 以確定一個類是否為特殊類型的實例:

// dynamic_cast_clr.cpp// compile with: /clrusing namespace System;void PrintObjectType( Object^o ) {  if( dynamic_cast<String^>(o) )   Console::WriteLine("Object is a String");  else if( dynamic_cast<int^>(o) )   Console::WriteLine("Object is an int");}int main() {  Object^o1 = "hello";  Object^o2 = 10;  PrintObjectType(o1);  PrintObjectType(o2);}

顯示多重繼承的類層次結構
顯示多繼承的類層次結構
指向類型 D 對象的指針可以安全地強制轉換為 B 或 C。但是,如果 D 強制轉換為指向 A 對象的指針,會導致 A 的哪個實例?這將導致不明確的強制轉換錯誤。若要避免此問題,可以執行兩個明確的轉換。例如:

// dynamic_cast_4.cpp// compile with: /c /GRclass A {virtual void f();};class B {virtual void f();};class D : public B {virtual void f();};void f() {  D* pd = new D;  B* pb = dynamic_cast<B*>(pd);  // first cast to B  A* pa2 = dynamic_cast<A*>(pb);  // ok: unambiguous}

當使用虛擬基類時,其他多義性問題會被引入??紤]下圖中顯示的類層次結構。

深入解析C++中的動態類型轉換與靜態類型轉換運算符

顯示虛擬基類的類層次結構
在此層次結構中,A 是虛擬基類。對于虛擬基類的定義。給定一個 E 類實例和一個指向 A 子對象的指針,指向 B 指針的 dynamic_cast 將失敗于多義性。必須先將強制轉換回完整 E 對象,然后以明確的方式反向沿層次結構,到達正確的 B 對象。
考慮下圖中顯示的類層次結構。

深入解析C++中的動態類型轉換與靜態類型轉換運算符

給定一個 E 類型的對象和一個指向 D 子對象的指針,從 D 子對象定位到最左側的 A 子對象,可進行三個轉換??梢詮?D 指針到 E 指針執行 dynamic_cast 轉換,然后從 E 到 B 執行轉換(dynamic_cast 或隱式轉換),最后從 B 到 A 執行隱式轉換。例如:

// dynamic_cast_5.cpp// compile with: /c /GRclass A {virtual void f();};class B : public A {virtual void f();};class C : public A { };class D {virtual void f();};class E : public B, public C, public D {virtual void f();};void f(D* pd) {  E* pe = dynamic_cast<E*>(pd);  B* pb = pe;  // upcast, implicit conversion  A* pa = pb;  // upcast, implicit conversion}

dynamic_cast 運算符還可以使用執行 “相互轉換”。使用同一個類層次結構可能進行指針轉換,例如: 從B 子對象轉換到D子對象(只要整個對象是類轉換型E。
考慮相互轉換,實際上從指針轉換到 D 到指針到最左側的 A 子對象只要兩個步驟??梢詮?D 到 B 執行相互轉換,然后從 B 到 A 執行隱式轉換。例如:

// dynamic_cast_6.cpp// compile with: /c /GRclass A {virtual void f();};class B : public A {virtual void f();};class C : public A { };class D {virtual void f();};class E : public B, public C, public D {virtual void f();};void f(D* pd) {  B* pb = dynamic_cast<B*>(pd);  // cross cast  A* pa = pb;  // upcast, implicit conversion}

通過 dynamic_cast 將 null 指針值轉換到目標類型的 null 指針值。
當您使用 dynamic_cast < type-id > ( expression )時,如果expression無法安全地轉換成類型 type-id,則運行時檢查會引起變換失敗。例如:

// dynamic_cast_7.cpp// compile with: /c /GRclass A {virtual void f();};class B {virtual void f();};void f() {  A* pa = new A;  B* pb = dynamic_cast<B*>(pa);  // fails at runtime, not safe;  // B not derived from A}

指針類型的非限定轉換的值是 null 指針。引用類型的非限定轉換會引發 bad_cast 異常。   如果 expression 不指向也不引用有效的對象,則__non_rtti_object 異常引發。
有關異常 __non_rtti_object 的解釋,請參見 typeid。
以下示例創建基類(結構 A)指針,為一個對象(結構 C)。這以及在該情況是虛函數,啟用運行時多態性。
該示例也在層次結構中調用非虛函數。

// dynamic_cast_8.cpp// compile with: /GR /EHsc#include <stdio.h>#include <iostream>struct A {  virtual void test() {    printf_s("in A/n");  }};struct B : A {  virtual void test() {    printf_s("in B/n");  }  void test2() {    printf_s("test2 in B/n");  }};struct C : B {  virtual void test() {    printf_s("in C/n");  }  void test2() {    printf_s("test2 in C/n");  }};void Globaltest(A& a) {  try {    C &c = dynamic_cast<C&>(a);    printf_s("in GlobalTest/n");  }  catch(std::bad_cast) {    printf_s("Can't cast to C/n");  }}int main() {  A *pa = new C;  A *pa2 = new B;  pa->test();  B * pb = dynamic_cast<B *>(pa);  if (pb)    pb->test2();  C * pc = dynamic_cast<C *>(pa2);  if (pc)    pc->test2();  C ConStack;  Globaltest(ConStack);  // will fail because B knows nothing about C  B BonStack;  Globaltest(BonStack);}

輸出:

in Ctest2 in Bin GlobalTest

static_cast 運算符
僅根據表達式中存在的類型,將 expression 轉換為 type-id, 類型。
語法

static_cast <type-id> ( expression ) 

備注
在標準 C++ 中,不進行運行時類型檢查來幫助確保轉換的安全。在 C++/CX 中,將執行編譯時和運行時檢查。
static_cast 運算符可用于將指向基類的指針轉換為指向派生類的指針等操作。此類轉換并非始終安全。
通常使用 static_cast 轉換數值數據類型,例如將枚舉型轉換為整型或將整型轉換為浮點型,而且你能確定參與轉換的數據類型。 static_cast 轉換安全性不如 dynamic_cast 轉換,因為 static_cast 不執行運行時類型檢查,而 dynamic_cast 執行該檢查。對不明確的指針的 dynamic_cast 將失敗,而 static_cast 的返回結果看似沒有問題,這是危險的。盡管 dynamic_cast 轉換更加安全,但是 dynamic_cast 只適用于指針或引用,而且運行時類型檢查也是一項開銷。
在下面的示例中,因為 D 可能有不在 B 內的字段和方法,所以行 D* pd2 = static_cast<D*>(pb); 不安全。但是,因為 D 始終包含所有 B,所以行 B* pb2 = static_cast<B*>(pd); 是安全的轉換。

// static_cast_Operator.cpp// compile with: /LDclass B {};class D : public B {};void f(B* pb, D* pd) {  D* pd2 = static_cast<D*>(pb);  // Not safe, D can have fields                  // and methods that are not in B.  B* pb2 = static_cast<B*>(pd);  // Safe conversion, D always                  // contains all of B.}

與 dynamic_cast 不同,pb 的 static_cast 轉換不執行運行時檢查。由 pb 指向的對象可能不是 D 類型的對象,在這種情況下使用 *pd2 會是災難性的。例如,調用 D 類(而非 B 類)的成員函數可能會導致訪問沖突。
dynamic_cast 和 static_cast 運算符可以在整個類層次結構中移動指針。然而,static_cast 完全依賴于轉換語句提供的信息,因此可能不安全。例如:

// static_cast_Operator_2.cpp// compile with: /LD /GRclass 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 確實指向 D 類型的對象,則 pd1 和 pd2 將獲取相同的值。如果 pb == 0,它們也將獲取相同的值。
如果 pb 指向 B 類型的對象,而非指向完整的 D 類,則 dynamic_cast 足以判斷返回零。但是,static_cast 依賴于程序員的斷言,即 pb 指向 D 類型的對象,因而只是返回指向那個假定的 D 對象的指針。
因此,static_cast 可以反向執行隱式轉換,而在這種情況下結果是不確定的。這需要程序員來驗證 static_cast 轉換的結果是否安全。
該行為也適用于類以外的類型。例如,static_cast 可用于將 int 轉換為 char。但是,得到的 char 可能沒有足夠的位來保存整個 int 值。同樣,這需要程序員來驗證 static_cast 轉換的結果是否安全。
static_cast 運算符還可用于執行任何隱式轉換,包括標準轉換和用戶定義的轉換。例如:

// static_cast_Operator_3.cpp// compile with: /LD /GRtypedef unsigned char BYTE;void f() {  char ch;  int i = 65;  float f = 2.5;  double dbl;  ch = static_cast<char>(i);  // int to char  dbl = static_cast<double>(f);  // float to double  i = static_cast<BYTE>(ch);}

static_cast 運算符可以將整數值顯式轉換為枚舉類型。如果整型值不在枚舉值的范圍內,生成的枚舉值是不確定的。
static_cast 運算符將 null 指針值轉換為目標類型的 null 指針值。
任何表達式都可以通過 static_cast 運算符顯式轉換為 void 類型。目標 void 類型可以選擇性地包含 const、volatile 或 __unaligned 特性。
static_cast 運算符無法轉換掉 const、volatile 或 __unaligned 特性。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91亚洲国产成人久久精品网站| 尤物yw午夜国产精品视频明星| 日本精品在线视频| 在线色欧美三级视频| 精品国产欧美成人夜夜嗨| 亚洲激情中文字幕| 亚洲欧美国产精品久久久久久久| 欧美黄网免费在线观看| 91九色蝌蚪国产| 国产精品网站入口| 久久久久亚洲精品成人网小说| 欧美大成色www永久网站婷| 少妇av一区二区三区| 欧美专区第一页| 欧美大片欧美激情性色a∨久久| 国产网站欧美日韩免费精品在线观看| 日韩精品在线影院| 亚洲国产古装精品网站| 日韩av在线不卡| 91免费的视频在线播放| 日韩av在线一区| 中国日韩欧美久久久久久久久| 欧美尺度大的性做爰视频| 97久久精品人人澡人人爽缅北| 亚洲香蕉成人av网站在线观看| 久久精品福利视频| 国产精品偷伦免费视频观看的| 欧美精品videossex性护士| 日韩在线观看免费全集电视剧网站| 中文字幕亚洲情99在线| 97精品欧美一区二区三区| 在线观看91久久久久久| 国产精品美女久久久免费| 亚洲国产另类 国产精品国产免费| 国产情人节一区| 狠狠躁夜夜躁人人爽天天天天97| 九九视频这里只有精品| 欧美综合一区第一页| 国产精品免费久久久久久| 久久久视频在线| 97香蕉超级碰碰久久免费软件| 久久亚洲精品一区| 欧美日韩国产成人在线| 国产精品久久久av久久久| 欧美日韩免费一区| 欧美日韩国产精品一区二区三区四区| 欧美另类99xxxxx| 亚洲毛片一区二区| 国产视频精品va久久久久久| 久久久久久久影视| 国产精品欧美久久久| 国产精品视频播放| 九九九热精品免费视频观看网站| 久久天天躁夜夜躁狠狠躁2022| 美女少妇精品视频| 一区二区三区视频免费| 国产成人精品亚洲精品| 欧美国产亚洲精品久久久8v| www.99久久热国产日韩欧美.com| 国内精品在线一区| 国产成人精品免费视频| 欧美亚洲国产成人精品| 欧美精品手机在线| 日韩欧美国产骚| 综合国产在线观看| 51午夜精品视频| 亚洲性线免费观看视频成熟| 黄色精品一区二区| 午夜精品一区二区三区在线视频| 亚洲性夜色噜噜噜7777| 国产精品电影一区| 亚洲第一国产精品| 日韩中文字幕免费视频| 亚洲精品国产精品久久清纯直播| 国产在线视频不卡| 日韩国产激情在线| 欧美丝袜美女中出在线| 美女999久久久精品视频| 91丝袜美腿美女视频网站| 亚洲欧美日韩在线高清直播| 国产一区红桃视频| 亚洲综合日韩中文字幕v在线| 韩国19禁主播vip福利视频| 国产精品直播网红| 日韩欧美a级成人黄色| 日本一欧美一欧美一亚洲视频| 一区二区三区视频免费| 久久夜色精品国产欧美乱| 久久久精品电影| 欧美视频在线免费| 97在线免费视频| 热久久视久久精品18亚洲精品| 久久国产精品久久精品| 中文字幕日韩在线播放| 国产精品美女免费看| 久久久久99精品久久久久| 一区二区在线视频播放| 精品女厕一区二区三区| 亚洲影院高清在线| 欧美成人精品不卡视频在线观看| 久久久国产视频91| 九九九久久国产免费| 国产精品久久久久aaaa九色| 久久伊人91精品综合网站| 欧美第一页在线| 91精品国产综合久久香蕉| 欧美成人精品h版在线观看| 欧美性在线观看| 亚洲国产精彩中文乱码av在线播放| 久久久久亚洲精品成人网小说| 69国产精品成人在线播放| 最近的2019中文字幕免费一页| 性欧美在线看片a免费观看| 国产精品老牛影院在线观看| 国产精品一香蕉国产线看观看| 国产97在线亚洲| 亚洲图片欧美日产| 亚洲国产一区二区三区四区| …久久精品99久久香蕉国产| 亚洲a级在线播放观看| 欧美成人小视频| 国产精品pans私拍| 日韩不卡中文字幕| 国产精品免费视频xxxx| 亚洲视频综合网| 国产精品欧美激情在线播放| 一本色道久久88综合亚洲精品ⅰ| 97在线观看免费| 精品欧美激情精品一区| 国产亚洲精品91在线| 国产精品久久久久久五月尺| 日韩精品久久久久| 成人在线国产精品| 欧美成人精品三级在线观看| 欧洲亚洲免费视频| 最近2019好看的中文字幕免费| 日韩欧美在线免费| 黑丝美女久久久| 日韩视频免费在线观看| 国产精品欧美一区二区| 久久五月天色综合| 高清亚洲成在人网站天堂| 成人免费高清完整版在线观看| 日韩美女在线观看| 国产精品视频午夜| 欧美夫妻性生活xx| 欧美日韩国产在线| 日韩在线观看av| 国产精品狼人色视频一区| 91高潮精品免费porn| 北条麻妃一区二区在线观看| 中日韩美女免费视频网站在线观看| 国产精品入口免费视| 欧美中文字幕视频在线观看| 亚洲性视频网站| 美女啪啪无遮挡免费久久网站| 国产精品aaaa| 欧美精品videos性欧美| 色诱女教师一区二区三区| 日韩成人网免费视频| 久久99视频免费| 九九热在线精品视频| 黑人极品videos精品欧美裸| 欧美激情欧美狂野欧美精品|