Berikut ini ikhtisar static_cast<>
dan dynamic_cast<>
khususnya terkait dengan pointer. Ini hanya jadwal 101 tingkat, tidak mencakup semua seluk-beluk.
static_cast <Type *> (ptr)
Ini mengambil pointer ptr
dan mencoba dengan aman melemparkannya ke pointer tipe Type*
. Pemeran ini dilakukan pada waktu kompilasi. Ini hanya akan melakukan pemeran jika jenisnya terkait. Jika jenisnya tidak terkait, Anda akan mendapatkan kesalahan kompiler. Sebagai contoh:
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 <Jenis *> (ptr)
Ini lagi mencoba untuk mengambil pointer ptr
dan dengan aman melemparkannya ke pointer tipe Type*
. Tetapi pemeran ini dieksekusi saat runtime, bukan waktu kompilasi. Karena ini adalah pemeran run-time, ini berguna terutama ketika dikombinasikan dengan kelas polimorfik. Faktanya, dalam kasus-kasus tertentu kelas-kelas tersebut harus polimorfik agar para pemain menjadi legal.
Pemain dapat masuk dalam salah satu dari dua arah: dari pangkalan ke turunan (B2D) atau dari turunan ke pangkalan (D2B). Ini cukup sederhana untuk melihat bagaimana gips D2B akan bekerja saat runtime. Entah ptr
berasal dari Type
atau tidak. Dalam kasus D2B dynamic_cast <> s, aturannya sederhana. Anda dapat mencoba untuk melemparkan apa pun ke hal lain, dan jika ptr
memang berasal dari Type
, Anda akan mendapatkan Type*
pointer kembali dynamic_cast
. Jika tidak, Anda akan mendapatkan pointer NULL.
Tapi gips B2D sedikit lebih rumit. Pertimbangkan kode berikut:
#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()
tidak tahu jenis objek apa yang CreateRandom()
akan kembali, sehingga para pemeran C-style Bar* bar = (Bar*)base;
jelas bukan tipe-safe. Bagaimana Anda bisa memperbaikinya? Salah satu caranya adalah dengan menambahkan fungsi seperti bool AreYouABar() const = 0;
ke kelas dasar dan kembali true
dari Bar
dan false
dari Foo
. Tetapi ada cara lain: gunakan 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;
}
Para pemain mengeksekusi pada saat runtime, dan bekerja dengan menanyakan objek (tidak perlu khawatir tentang bagaimana untuk sekarang), menanyakannya apakah itu tipe yang kita cari. Jika ya, dynamic_cast<Type*>
kembalikan pointer; selain itu mengembalikan NULL.
Agar casting berbasis-ke-turunan ini dapat bekerja menggunakan dynamic_cast<>
, Base, Foo dan Bar harus sesuai dengan apa yang disebut Standar sebagai tipe polimorfik . Untuk menjadi tipe polimorfik, kelas Anda harus memiliki setidaknya satu virtual
fungsi. Jika kelas Anda bukan tipe polimorfik, penggunaan basis-ke-turunan dynamic_cast
tidak akan dikompilasi. Contoh:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
Menambahkan fungsi virtual ke basis, seperti virtual dtor, akan membuat tipe Base dan Der polimorfik:
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<>
bekerja di belakang layar (atau seberapa banyak C ++ bekerja), buku yang bagus (itu juga cukup mudah dibaca untuk sesuatu yang sangat teknis) adalah Lippman "Inside the C ++ Object Model". Juga buku-buku "Desain dan Evolusi C ++" Stroustrup dan "Bahasa Pemrograman C ++" adalah sumber yang bagus, tetapi buku Lippman didedikasikan untuk bagaimana C ++ bekerja 'di belakang layar'.