C++强制类型转换操作符 dynamic_cast
dynamic_cast是四個(gè)強(qiáng)制類型轉(zhuǎn)換操作符中最特殊的一個(gè),它支持運(yùn)行時(shí)識別指針或引用。
?
>>>>>>>>>>>編譯器的RTTI設(shè)置>>>>>>>>>>>
dynamic_cast提供RTTI(Run-Time Type Information),也就是運(yùn)行時(shí)類型識別。它對編譯器有要求,需要編譯器啟動“運(yùn)行時(shí)類型信息”這一選項(xiàng)。當(dāng)編譯器不開啟RTTI時(shí),運(yùn)行含有dynamic_cast操作符的程序時(shí)會出現(xiàn)一個(gè)警告:
warning C4541: “dynamic_cast”用在了帶 /GR- 的多態(tài)類型“ANIMAL”上;可能導(dǎo)致不可預(yù)知的行為VS2010在默認(rèn)下是開啟RTTI的,也可以自己手動去開啟或者關(guān)閉,操作如下:
視圖->解決方案資源管理器 在打開的解決方案管理器中,對著項(xiàng)目名稱右擊,選擇屬性 配置屬性-〉C/C++?
>>>>>>>>>>>>>步入正題>>>>>>>>>>>>>
- dynamic_cast主要用于“安全地向下轉(zhuǎn)型”
dynamic_cast用于類繼承層次間的指針或引用轉(zhuǎn)換。主要還是用于執(zhí)行“安全的向下轉(zhuǎn)型(safe downcasting)”,也即是基類對象的指針或引用轉(zhuǎn)換為同一繼承層次的其他指針或引用。至于“先上轉(zhuǎn)型”(即派生類指針或引用類型轉(zhuǎn)換為其基類類型),本身就是安全的,盡管可以使用dynamic_cast進(jìn)行轉(zhuǎn)換,但這是沒必要的, 普通的轉(zhuǎn)換已經(jīng)可以達(dá)到目的,畢竟使用dynamic_cast是需要開銷的。
1 class Base 2 { 3 public: 4 Base(){}; 5 virtual void Show(){cout<<"This is Base calss";} 6 }; 7 class Derived:public Base 8 { 9 public: 10 Derived(){}; 11 void Show(){cout<<"This is Derived class";} 12 }; 13 int main() 14 { 15 Base *base ; 16 Derived *der = new Derived; 17 //base = dynamic_cast<Base*>(der); //正確,但不必要。 18 base = der; //先上轉(zhuǎn)換總是安全的 19 base->Show(); 20 system("pause"); 21 }- ?dynamic_cast與繼承層次的指針
對于“向下轉(zhuǎn)型”有兩種情況。一種是基類指針?biāo)笇ο笫桥缮愵愋偷?#xff0c;這種轉(zhuǎn)換是安全的;另一種是基類指針?biāo)笇ο鬄榛愵愋?#xff0c;在這種情況下dynamic_cast在運(yùn)行時(shí)做檢查,轉(zhuǎn)換失敗,返回結(jié)果為0;
#include "stdafx.h" #include<iostream> using namespace std;class Base { public:Base(){};virtual void Show(){cout<<"This is Base calss";} }; class Derived:public Base { public:Derived(){};void Show(){cout<<"This is Derived class";} }; int main() { //這是第一種情況Base* base = new Derived;if(Derived *der= dynamic_cast<Derived*>(base)){cout<<"第一種情況轉(zhuǎn)換成功"<<endl;der->Show();cout<<endl;}//這是第二種情況Base * base1 = new Base;if(Derived *der1 = dynamic_cast<Derived*>(base1)){cout<<"第二種情況轉(zhuǎn)換成功"<<endl;der1->Show();}else {cout<<"第二種情況轉(zhuǎn)換失敗"<<endl;}delete(base);delete(base1);system("pause"); }運(yùn)行結(jié)果:
- ?dynamic_cast和引用類型
在前面的例子中,使用了dynamic_cast將基類指針轉(zhuǎn)換為派生類指針,也可以使用dynamic_cast將基類引用轉(zhuǎn)換為派生類引用。
同樣的,引用的向上轉(zhuǎn)換總是安全的:
Derived c;Derived & der2= c;Base & base2= dynamic_cast<Base&>(der2);//向上轉(zhuǎn)換,安全base2.Show();所以,在引用上,dynamic_cast依舊是常用于“安全的向下轉(zhuǎn)型”。與指針一樣,引用的向下轉(zhuǎn)型也可以分為兩種情況,與指針不同的是,并不存在空引用,所以引用的dynamic_cast檢測失敗時(shí)會拋出一個(gè)bad_cast異常:
int main() { //第一種情況,轉(zhuǎn)換成功 Derived b ;Base &base1= b;Derived &der1 = dynamic_cast<Derived&>(base1);cout<<"第一種情況:";der1.Show();cout<<endl;//第二種情況 Base a ;Base &base = a ;cout<<"第二種情況:";try{Derived & der = dynamic_cast<Derived&>(base);}catch(bad_cast){cout<<"轉(zhuǎn)化失敗,拋出bad_cast異常"<<endl;}system("pause"); }運(yùn)行結(jié)果:
?
- 使用dynamic_cast轉(zhuǎn)換的Base類至少帶有一個(gè)虛函數(shù)
? ? 當(dāng)一個(gè)類中擁有至少一個(gè)虛函數(shù)的時(shí)候,編譯器會為該類構(gòu)建出一個(gè)虛函數(shù)表(virtual method table),虛函數(shù)表記錄了虛函數(shù)的地址。如果該類派生了其他子類,且子類定義并實(shí)現(xiàn)了基類的虛函數(shù),那么虛函數(shù)表會將該函數(shù)指向新的地址。虛表是C++多態(tài)實(shí)現(xiàn)的一個(gè)重要手段,也是dynamic_cast操作符轉(zhuǎn)換能夠進(jìn)行的前提條件。當(dāng)類沒有虛函數(shù)表的時(shí)候(也即一個(gè)虛函數(shù)都沒有定義),dynamic_cast無法使用RTTI,不能通過編譯(個(gè)人猜想...有待驗(yàn)證)。
當(dāng)然,虛函數(shù)表的建立對效率是有一定影響的,構(gòu)建虛函數(shù)表、由表查詢函數(shù) 都需要時(shí)間和空間上的消耗。所以,除了必須聲明virtual(對于一個(gè)多態(tài)基類而言),不要輕易使用virtual函數(shù)。對于虛函數(shù)的進(jìn)一步了解,可以查看《Effective C++》
條款07:為多態(tài)基類聲明virtual析構(gòu)函數(shù)。
轉(zhuǎn)載于:https://www.cnblogs.com/QG-whz/p/4517336.html
總結(jié)
以上是生活随笔為你收集整理的C++强制类型转换操作符 dynamic_cast的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 207-Course Schedule
- 下一篇: 关于Android C++的NDK环境搭