Bezpieczne rzutowanie typów (type casting) w C++ zapewniane jest za pomocą operatorów rzutowania: static_cast, dynamic_cast, const_cast, reinterpret_cast.
nullptr dla wskaźników lub zgłosi wyjątek dla referencji.Kiedy używać:
dynamic_cast z wirtualnymi bazami. Do konwersji między prostymi/kompatybilnymi typami — static_cast.Przykład:
struct Base { virtual ~Base() {} }; struct Derived : Base { void foo() {} }; void test_cast(Base* base) { // Bezpieczne rzutowanie do niższego klasą Derived* d = dynamic_cast<Derived*>(base); if (d) { d->foo(); } }
Pytanie: Czy można skonwertować obiekt klasy podstawowej do pochodnej przy użyciu static_cast, jeśli obiekt w rzeczywistości nie jest instancją klasy pochodnej?
Odpowiedź: Tak, static_cast kompiluje się, ale zachowanie będzie niezdefiniowane, jeśli obiekt nie jest rzeczywiście obiektem klasy pochodnej. Tylko dynamic_cast gwarantuje bezpieczeństwo takiego rzutowania. Użycie static_cast do downcastu jest dozwolone tylko wtedy, gdy jesteś pewny rzeczywistego typu obiektu.
Historia
W dużym systemie embedded rzutowania między klasą rodzicielską a dziecinną były realizowane przez static_cast. W niektórych przypadkach prowadziło to do awarii podczas próby uzyskania dostępu do nieistniejących pól — program próbował interpretować pamięć innego typu.
Historia
Przy opracowywaniu architektury pluginów programiści używali reinterpret_cast do rzutowania wskaźników między różnymi typami, co prowadziło do odczytu śmieci i awarii w czasie wykonywania, zwłaszcza podczas próby dynamicznego rzutowania przez DLL.
Historia
W ogólnym korporacyjnym frameworku zapomniano o wirtualnych destruktorach w klasie podstawowej, co uniemożliwiało prawidłowe działanie dynamic_cast i prowadziło do wycieków pamięci i uszkodzeń przy usuwaniu obiektu przez wskaźnik na klasę podstawową.