İşte static_cast<>
ve dynamic_cast<>
özellikle işaretçilerle ilgili bir özet . Bu sadece 101 seviyeli bir yıkım, tüm karmaşıklıkları kapsamıyor.
static_cast <Tür *> (ptr)
Bu, işaretçiyi içeri alır ptr
ve güvenli bir şekilde bir işaretçiye aktarmaya çalışır Type*
. Bu döküm derleme zamanında yapılır. Döküm işlemini yalnızca tür türleri ilişkili olduğunda gerçekleştirir. Türler ilişkili değilse, bir derleyici hatası alırsınız. Örneğin:
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 <Tür *> (ptr)
Bu, işaretçiyi tekrar içeri almaya ptr
ve güvenli bir şekilde bir işaretçiye aktarmaya çalışır Type*
. Ancak bu döküm, derleme zamanında değil, çalışma zamanında yürütülür. Bu bir çalışma zamanı döküm olduğundan, özellikle polimorfik sınıflarla birleştirildiğinde yararlıdır. Aslında, certian vakalarda , oyuncuların yasal olabilmesi için sınıfların polimorfik olması gerekir .
Kalıplar iki yönden birine gidebilir: bazdan türetilmiş (B2D) veya türetilmiş bazdan (D2B). D2B yayınlarının çalışma zamanında nasıl çalışacağını görmek yeterince basit. Ya ptr
türetilmiştir Type
ya da değildir. D2B dynamic_cast <> s durumunda kurallar basittir. Başka bir şeye herhangi bir şey atmayı deneyebilirsiniz ve eğer ptr
aslında türetilmişse Type
, bir Type*
işaretçi geri alırsınız dynamic_cast
. Aksi takdirde, bir NULL işaretçisi alırsınız.
Ancak B2D oyuncuları biraz daha karmaşıktır. Aşağıdaki kodu göz önünde bulundurun:
#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()
ne tür bir nesnenin CreateRandom()
geri döneceğini söyleyemediğinden , C stili kadro Bar* bar = (Bar*)base;
kesinlikle güvenli değildir. Bunu nasıl düzeltebilirsin? Tek yönlü bool gibi bir işlev eklemek olacaktır AreYouABar() const = 0;
temel sınıf ve iade true
gelen Bar
ve false
gelen Foo
. Ancak başka bir yol daha var 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;
}
Yayınlar çalışma zamanında yürütülür ve nesneyi sorgulayarak çalışır (şu an için nasıl endişelenmenize gerek yoktur), aradığımız tür olup olmadığını sorar. Öyleyse, dynamic_cast<Type*>
bir işaretçi döndürür; aksi takdirde NULL döndürür.
Bu tabandan türetilmiş dökümün çalışabilmesi için dynamic_cast<>
, Standardın polimorfik tipler olarak adlandırdığı Base, Foo ve Bar olmalıdır . Polimorfik bir tip olabilmek için sınıfınızın en az bir virtual
işlevi olmalıdır. Sınıflarınız polimorfik türler değilse, tabandan türetilmiş kullanımı dynamic_cast
derlenmeyecektir. Misal:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
Tabana sanal bir dtor gibi bir sanal işlev eklemek hem Base hem de Der polimorfik türlerini yapar:
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}
dynamic_cast<>
Sahnelerin arkasında nasıl çalıştığına (veya C ++ 'ın ne kadar işe yaradığına) dair iyi bir fikir edinmek istiyorsanız , iyi bir kitap (bu kadar teknik bir şey için de okunması oldukça kolaydır) Lippman'ın "C ++ Nesne Modeli İçinde" dir. Ayrıca Stroustrup'un "C ++ Tasarım ve Evrimi" ve "C ++ Programlama Dili" kitapları iyi kaynaklardır, ancak Lippman'ın kitabı C ++ 'ın' perde arkasında 'nasıl çalıştığına adanmıştır.