3 回答
TA貢獻1966條經驗 獲得超4個贊
這是一個簡介static_cast<>,dynamic_cast<>特別是它們與指針有關。這只是一個101級的破舊,它并沒有涵蓋所有錯綜復雜的內容。
static_cast <Type *>(ptr)
這ptr會將指針接入并嘗試將其安全地轉換為類型的指針Type*。這個演員表是在編譯時完成的。如果類型類型相關,它將僅執行強制轉換。如果類型不相關,則會出現編譯器錯誤。例如:
class B {};class D : public B {};class X {};int main(){
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;}dynamic_cast <Type *>(ptr)
這再次嘗試將指針插入ptr并安全地將其轉換為類型的指針Type*。但是這個演員表是在運行時執行的,而不是編譯時。因為這是一個運行時轉換,所以特別是在與多態類組合時非常有用。實際上,在certian情況下,類必須是多態的,以使轉換合法。
演員可以進入兩個方向之一:從基礎到派生(B2D)或從派生到基礎(D2B)。這很簡單,可以看到D2B強制轉換如何在運行時運行。要么ptr是源于,Type要么不是。在D2B dynamic_cast <> s的情況下,規則很簡單。您可以嘗試將任何內容轉換為其他內容,如果ptr實際上是派生出來的Type,那么您將獲得一個Type*指針dynamic_cast。否則,您將獲得一個NULL指針。
但是B2D演員陣容有點復雜。請考慮以下代碼:
#include <iostream>using namespace std;class Base{public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};};class Foo : public Base{public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }};class Bar : public Base{public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }};Base* CreateRandom(){
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;}int main(){
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;}main()不知道什么樣的對象CreateRandom()會返回,所以C風格的演員Bar* bar = (Bar*)base;陣容絕對不是類型安全的。你怎么能解決這個問題?一種方式是像布爾函數添加AreYouABar() const = 0;到基類,并返回true從Bar和false從Foo。但還有另一種方法:使用dynamic_cast<>:
int main(){
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;}強制轉換在運行時執行,并通過查詢對象來工作(無需擔心現在如何),詢問它是否是我們正在尋找的類型。如果是,則dynamic_cast<Type*>返回指針; 否則返回NULL。
為了使這個基礎到派生的轉換能夠使用dynamic_cast<>,Base,Foo和Bar必須是Standard所謂的多態類型。要成為多態類型,您的類必須至少具有一個virtual函數。如果您的類不是多態類型,dynamic_cast則不會編譯從基礎到派生的使用。例:
class Base {};class Der : public Base {};int main(){
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;}向基礎添加虛擬功能(例如虛擬dtor)將同時生成Base和Der多態類型:
class Base {public:
virtual ~Base(){};};class Der : public Base {};int main(){
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;}TA貢獻2051條經驗 獲得超10個贊
除非您實現自己的手動RTTI(并繞過系統),否則無法dynamic_cast直接在C ++用戶級代碼中實現。dynamic_cast與C ++實現的RTTI系統密切相關。
但是,為了幫助您理解RTTI(以及dynamic_cast更多),您應該閱讀<typeinfo>標題和typeid操作符。這將返回與您手頭的對象相對應的類型信息,您可以從這些類型的信息對象中查詢各種(有限的)事物。
TA貢獻1860條經驗 獲得超8個贊
不僅僅是C中的代碼,我認為英語定義就足夠了:
給定一個類Base,它有一個派生類Derived,dynamic_cast當且僅當指向的實際對象實際上是Derived對象時,才會將Base指針轉換為Derived指針。
class Base { virtual ~Base() {} };class Derived : public Base {};class Derived2 : public Base {};class ReDerived : public Derived {};void test( Base & base ){
dynamic_cast<Derived&>(base);}int main() {
Base b;
Derived d;
Derived2 d2;
ReDerived rd;
test( b ); // throw: b is not a Derived object
test( d ); // ok
test( d2 ); // throw: d2 is not a Derived object
test( rd ); // ok: rd is a ReDerived, and thus a derived object}在示例中,調用test將不同的對象綁定到引用Base。在內部,參考downcasted的引用Derived類型安全方式:喪氣將只對那些情況下,被引用的對象確實是一個實例成功Derived。
- 3 回答
- 0 關注
- 519 瀏覽
添加回答
舉報
