18 Mart 2020 Çarşamba

dynamic_cast - Kalıtım Varsa Kullanılır

Giriş
Açıklaması şöyle.
dynamic_cast can only be used with pointers and references to classes (or with void*). Its purpose is to ensure that the result of the type conversion points to a valid complete object of the destination pointer type.
This naturally includes pointer upcast (converting from pointer-to-derived to pointer-to-base), in the same way as allowed as an implicit conversion.
But dynamic_cast can also downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type.
Açıklaması şöyle.
Safely converts pointers and references to classes up, down, and sideways along the inheritance hierarchy.
Upcast - Kalıtan Sınıftan Ata Sınıfa Çevirir
Özel bir durum yok.

Downcast - Ata sınıftan Kalıtan Sınıfa Çevirir
Örnek
Elimizde şöyle bir kod olsun.
#include <unordered_set>

struct  Base{};
struct Derived : public Base{ Derived() = default; };

std::unordered_set<Base *> set;
set.insert(new Derived{});
Bunu başka kalıtan tipten bir başka set'e çevirmek için şöyle yaparız.
std::unordered_set<Derived *> second;
for (auto& it : first) {
  auto derived_ptr = dynamic_cast<Derived *>(&*it);
  if (nullptr != derived_ptr) {
    second.insert(derived_ptr);
  }
}
Örnek - static_cast ve dynamic_cast Farkı
1. Downcast yaparken dynamic_cast ve static_cast arasında fark vardır. static_cast herhangi bir kontrol uygulamaz. dynamic_cast ise işlemin başarılı olup olmadığını kontrol eder.
Yani dynamic_cast derleme esnasında değil de çalışma esnasında kontrol için kullanılır.
A* p = new B(); 
B* pB = static_cast<B*>(p); // Checks if B is related to A in an inheritance 
     // ^^^^^^^^^^^^^^^^^^^    hierarchy. Fails to compile if not.
Şöyle yaparız.
A* pA = new B();
B* pB = dynamic_cast<B*>(pA); // Checks if pA actually points to an instance of B
     // ^^^^^^^^^^^^^^^^^^^^     at runtime, and returns nullptr if not
if(pB) {
  // do stuff with B
}
RTTI Seçeneği
dynamic_cast kullanabilmek için RTTI seçeneği ile derlemek gerekir. dynamic_cast deference edilen bellek alanı geçersiz ise undefined çalışır.

Visual Studio ile RTT desteğini kapatmak için projeye sağ tıklayıp Properties / C/C++ / Language / Enable Run-Time Type Information seçeneği değiştirilmeli.

2. Multiple inheritance olduğu durumda (Base, Derived1,Derived2 olsun) Derived1'i Derived2'ye döndürmek için kullanılır.

Downcast Yaparken Ata Sınıf Polymorphic Olmalıdır
Ata sınıfın en bir tane virtual metodu olmalıdır. Şöyle yapabiliriz.
class Base
{
   virtual ~Base() {}
};
Downcast Yaparken Reference Olarak Kullanmak
Eğer reference döndürülecekse ve dönüşüm başaralı olmazsa dynamic_cast bad_cast exception atar.

Downcast Yaparken Pointer Olarak Kullanmak
Eğer pointer döndürülecekse ve dönüşüm başaralı olmazsa dynamic_cast NULL değeri döner. Şöyle yaparız.
Base *base = ...;
Derived *derived = dynamic_cast<Derived*>(base);
if(derived) {  // do stuff
}

Hiç yorum yok:

Yorum Gönder