dynamic_cast的使用條件


今天從學長那里聽來一道騰訊的面試題,問的是C++中的dynamic_cast在什么情況下是錯誤的?我認為這個問題的更好的描述是dynamic_cast的使用條件是什么?

C++提供了兩種方式來支持RTTI,dynamic_cast是其中一種,另一種是typeid()。表面上看,dynamic_cast有兩種形式:

Base *pBase = new Derived();

Derived *pDerived = dynamic_cast<Derived *> pBase;


Base refBase = Derived();

Derived &refDerived = dynamic_cast<Derived &> refBase


即dynamic_cast用於將基類的引用或指針轉化為派生類的引用或指針。但使用條件是:1、基類的指針或引用確實綁定到派生類的對象上;2、只有當基類至少含有一個虛函數的時候才能使用dynamic_cast。原因是RTTI機制依賴於虛函數表(inside C++ object model第一章給出了解釋),而dynamic_cast是RTTI的一種,所以必須要有虛函數表的支持,也就是要虛類中至少有一個虛函數。

那么,dynamic_cast有什么好處呢?

我們知道,基類的指針即使指向的是派生類的對象,但通過基類的指針也只能訪問到基類中包含的public成員,那如果想要訪問派生類中新增的public成員呢?這就需要將基類的的指針動態類型轉化為派生類的指針。見以下代碼:

#include<iostream>
using namespace std;
class base{
public:
base(int x):a(x){ }
virtual void fcn(){ } //要有虛函數
int a;
};

class derived:public base{
public:
derived(int x,int y):base(x),b(y){ }
int b;
};

int main(){
base *pbase = new derived(100, 200);
cout << pbase->a << endl;
//cout << pbase->b << endl; //不能通過基類的指針訪問派生類新增的public成員

derived *pderived = dynamic_cast<derived *>(pbase);

cout << pderived->a << endl;
cout << pderived->b << endl;
}

如何對dynamic_cast轉化是否成功進行判斷,從而選擇進行基類的操作還是進行派生類的操作呢?見下面的代碼:

#include<iostream>
using namespace std;
class base{
public:
base(int x):a(x){ }
virtual void fcn(){ } //要有虛函數
int a;
};

class derived:public base{
public:
derived(int x,int y):base(x),b(y){ }
int b;
};

int main(){
base *pbase0 = new base(100);
base *pbase1 = new derived(100, 200);


if(NULL != dynamic_cast<derived *>(pbase0)){
cout << dynamic_cast<derived *>(pbase0)->b << endl;
cout<<"derived"<<endl;
}else{
cout << pbase0->a << endl;
cout<<"base"<<endl;
}

if(derived *pderived = dynamic_cast<derived *>(pbase1)){
cout << dynamic_cast<derived *>(pbase1)->b << endl;
cout<<"derived"<<endl;
}else{
cout << pbase1->a << endl;
cout<<"base"<<endl;
}
}
運行結果如下:

100
base
200
derived

《C++ primer》第5版P731上給出了以下代碼框架:

if(Derived *dp = dynamic_cast<derived *>(bp)){

//使用bp指向的Derived對象

}else{

//使用bp指向的Base對象

}

在vs和gcc下測試過:如果bp指向的不是派生類的對象而是基類的對象的話,那么兩種編譯器下都不能通過編譯!!!這樣的運行時動態類型判斷也就沒有意義了。這種寫法值得商榷!


如果是引用的話,當轉化不成功時會拋出std::bad_cast異常,詳見《C++ primer》第5版P731。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com