Aby zrozumieć system rzutowania, należy zanurkować w modelu obiektowym.
Klasyczne przedstawienie prostego modelu hierarchii jest powstrzymywanie: że jeśli B
wywodzi A
następnie przedmiotem B
będzie w rzeczywistości zawierać A
podobiekt obok własnych cech.
W tym modelu downcasting jest prostą manipulacją wskaźnikową, przez offset znany w czasie kompilacji, który zależy od układu pamięci B
.
To co static_cast zrobić: statyczny obsada dubbingu jest statyczna, ponieważ obliczanie, co jest konieczne dla obsada odbywa się w czasie kompilacji, czy to wyżeł arytmetycznych lub konwersji (*).
Jednak, gdy kopie w dziedziczeniu virtual
stają się nieco trudniejsze. Głównym problemem jest to, że z dziedziczeniem wszystkie podklasy współdzielą to samo wystąpienie podobiektu. W tym celu B
będzie miał wskaźnik do A
, zamiast właściwego A
, a obiekt klasy bazowej A
zostanie utworzony poza B
.
Dlatego w czasie kompilacji niemożliwe jest wydedukowanie niezbędnej arytmetyki wskaźnika: zależy to od typu środowiska wykonawczego obiektu.
Zawsze, gdy istnieje zależność typu czasu pracy, potrzebne są informacje RTTI (Informacje o typie RunTime), a korzystanie z RTTI dla rzutowania jest zadaniem dynamic_cast.
Podsumowując:
- kompilacji przygnębiony:
static_cast
- run-time przygnębiony:
dynamic_cast
Pozostałe dwa są również w czasie kompilacji rzuca, ale są tak specyficzne, że łatwo zapamiętać, do czego służą ... i są śmierdzące, więc lepiej nie używać ich w ogóle.
(*) Jak zauważono przez @curiousguy w komentarzach, dotyczy to tylko downcastingu. A static_cast
pozwala na upcasting niezależnie od wirtualnego lub prostego dziedziczenia, chociaż wtedy obsada jest również niepotrzebna.
Dobra odpowiedź, która pozwoliła mi zrozumieć, jak naprawdę działa wirtualne dziedzictwo!+1 – undu
Podoba mi się twoja odpowiedź, ale OP najwyraźniej pytał o błąd dla DOWNCASTING zamiast upcasting. – h9uest
@ h9uest: Dzięki, że pokazałam tę wpadkę, zmieniłam "casting" na "downcasting" i wszystko jest już dobrze. –