Ugrás a tartalomhoz

C++ dynamic cast

A Wikiszótárból, a nyitott szótárból


Főnév

C++ dynamic cast (tsz. C++ dynamic casts)

  1. (informatika) A dynamic_cast C++-ban egy speciális típuskonverziós operátor, amelyet futásidejű típusellenőrzéssel rendelkező típuskonverzióhoz használunk. Ez elsősorban polimorf osztályokkal (olyan osztályokkal, amelyek legalább egy virtuális függvényt tartalmaznak) működik.



Mire jó a dynamic_cast?

  • Lefelé irányuló kasztolás (downcasting): Egy alaposztály mutatójának vagy referenciájának átalakítása egy származtatott osztály mutatójává/referenciájává biztonságos módon.
  • Futásidejű típusellenőrzés: Ha az átalakítás nem lehetséges, a dynamic_cast nullptr-t ad vissza (mutatók esetén) vagy kivételt dob (referenciák esetén).
  • RTTI (Run-Time Type Information) használata: dynamic_cast csak olyan osztályokkal működik, amelyek tartalmaznak legalább egy virtuális függvényt.



Példák dynamic_cast használatára

1. Lefelé irányuló kasztolás (biztonságos downcasting)

#include <iostream>

class Base {
public:
    virtual ~Base() {} // Virtuális destruktor, hogy RTTI működjön
};

class Derived : public Base {
public:
    void sayHello() {
        std::cout << "Hello from Derived!" << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived(); // Alaposztály mutatója egy Derived objektumra mutat

    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // Lefelé irányuló kasztolás

    if (derivedPtr) {
        derivedPtr->sayHello(); // Sikeres átalakítás
    } else {
        std::cout << "Conversion failed!" << std::endl;
    }

    delete basePtr;
    return 0;
}

Magyarázat:
- Ha basePtr ténylegesen egy Derived objektumot tartalmaz, akkor dynamic_cast sikeres lesz. - Ha nem, dynamic_cast nullptr-t ad vissza.



2. Nem megfelelő kasztolás (dynamic_cast sikertelen)

#include <iostream>

class Base {
public:
    virtual ~Base() {} // Virtuális destruktor, hogy RTTI működjön
};

class Derived : public Base {};

class Unrelated {}; // Teljesen más osztály

int main() {
    Base* basePtr = new Base();
    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // Sikertelen kasztolás

    if (derivedPtr) {
        std::cout << "Conversion succeeded!" << std::endl;
    } else {
        std::cout << "Conversion failed!" << std::endl;
    }

    delete basePtr;
    return 0;
}

Magyarázat:
- Mivel basePtr valójában nem egy Derived objektumra mutat, a dynamic_cast sikertelen, és nullptr-t ad vissza.



3. Referencia kasztolás (std::bad_cast kivétellel)

#include <iostream>
#include <typeinfo>

class Base {
public:
    virtual ~Base() {}
};

class Derived : public Base {};

int main() {
    try {
        Base baseObj;
        Derived& derivedRef = dynamic_cast<Derived&>(baseObj); // Sikertelen kasztolás
    } catch (const std::bad_cast& e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }

    return 0;
}

Magyarázat:
- Ha mutatót kasztolunk dynamic_cast-tal és sikertelen a kasztolás, akkor nullptr-t kapunk. - Ha referenciát kasztolunk, akkor a dynamic_cast std::bad_cast kivételt dob.



Mire nem jó a dynamic_cast?

  1. Nem működik virtuális függvények nélküli osztályokkal
    • dynamic_cast csak olyan osztályokon működik, amelyek tartalmaznak legalább egy virtuális függvényt.
  2. Nem működik teljesen eltérő osztályok között
    • Nem lehet két különböző osztályt dynamic_cast-tal átalakítani.
  3. Futásidejű költsége van
    • A dynamic_cast RTTI-t (Run-Time Type Information) használ, ezért lassabb lehet, mint a static_cast.



Összegzés

  • Ha biztos vagy benne, hogy a konverzió érvényes: static_cast
  • Ha futásidőben kell ellenőrizni, hogy egy mutató tényleg egy származtatott osztály példányára mutat: dynamic_cast
  • Ha nem biztos, hogy egy referenciát le lehet kasztolni, és kezelni kell az esetleges hibát: dynamic_cast referencia esetén std::bad_cast kivételt dob.

A dynamic_cast tehát egy biztonságosabb, de lassabb módja a típuskonverziónak polimorf osztályok között.