std::dynamic pointer cast (tsz. std::dynamic pointer casts)
std::dynamic_pointer_cast
a C++ Standard Library egyik fontos eszköze az okos pointerek (smart pointers), azon belül is a std::shared_ptr
típus biztonságos futásidejű típuskonverziójára. Olyan típuskonverzióra használjuk, ahol az öröklődési hierarchia miatt szükség lehet dinamikus castolásra — például amikor egy Base
osztályra mutató shared_ptr
-t szeretnénk Derived
osztályra mutató shared_ptr
-ré alakítani.
std::shared_ptr<Derived> ptr2 = std::dynamic_pointer_cast<Derived>(ptr1);
ptr1
egy std::shared_ptr<Base>
típusú pointer.Base
osztálynak virtuális destruktora kell, hogy legyen, különben a dynamic_cast
nem fog működni helyesen.
A std::dynamic_pointer_cast
a dynamic_cast
C++ kulcsszóra épül, és csak akkor működik, ha a típusok között valóban van érvényes, biztonságos downcast (pl. Base*
→ Derived*
).
Ha a cast nem sikeres (pl. a Base
objektum valójában nem Derived
típusú), akkor az eredmény egy üres (nullptr
) shared_ptr
.
dynamic_cast
csak akkor működik, ha az osztály polimorf (legalább egy virtuális metódusa van).std::shared_ptr
-rel működik (nem működik unique_ptr
-rel, arra static_cast
-al egyedi sablonmegoldást kell írni).
#include <iostream>
#include <memory>
class Base {
public:
virtual ~Base() = default;
};
class Derived : public Base {
public:
void hello() {
std::cout << "Hello from Derived\n";
}
};
int main() {
std::shared_ptr<Base> basePtr = std::make_shared<Derived>();
std::shared_ptr<Derived> derivedPtr = std::dynamic_pointer_cast<Derived>(basePtr);
if (derivedPtr) {
derivedPtr->hello(); // Sikeres cast, hívható a Derived metódusa
} else {
std::cout << "Cast failed\n";
}
// Sikertelen példa
std::shared_ptr<Base> baseOnly = std::make_shared<Base>();
std::shared_ptr<Derived> shouldFail = std::dynamic_pointer_cast<Derived>(baseOnly);
if (!shouldFail)
std::cout << "Sikertelen cast - nem Derived\n";
}
static_pointer_cast
és dynamic_pointer_cast
között?Tulajdonság | static_pointer_cast
|
dynamic_pointer_cast
|
---|---|---|
Ellenőrzés | Fordításkor (compile-time) | Futásidőben (run-time) |
Polimorfia szükséges? | Nem | Igen (virtuális metódus kell) |
Sikeresség garantált? | Nem (felelősség a programozóé) | Csak akkor sikeres, ha valóban lehetséges |
Üres pointer visszatérhet? | Nem | Igen, ha a cast nem sikerül |
shared_ptr<Base>
kollekcióban (pl. std::vector<std::shared_ptr<Base>>
), majd típusspecifikus feldolgozás.
Nem virtuális destruktor a bázisosztályban:
class Base {}; // NINCS virtual ~Base()
→ dynamic_cast
nem működik, vagy viselkedése nem definiált.
Nem ellenőrzi a visszatérési értéket:
ptr->doSomething(); // Ha ptr nullptr, akkor crash
Nem használható unique_ptr
-rel:
Ha unique_ptr
-t akarsz dinamikusan castolni, azt kézzel kell megírni:
std::unique_ptr<Base> base = std::make_unique<Derived>();
Derived* raw = dynamic_cast<Derived*>(base.get());
if (raw) {
std::unique_ptr<Derived> derived(raw);
base.release(); // Fontos!
}
std::dynamic_pointer_cast
az eredeti shared_ptr
-ből származtat egy új shared_ptr
-t, megtartva a reference countot, és dinamikus típusellenőrzést hajt végre dynamic_cast
segítségével. Ha a konverzió sikeres, akkor új shared_ptr
-t kapsz a leszármazott típusra, ha nem, akkor nullptr
.
std::dynamic_pointer_cast
dinamikus, biztonságos típuskonverzió shared_ptr
típusok között.nullptr
-t ad vissza, ha a cast nem sikerül.virtual
metódus kötelező).