Rzutowanie typów kompatybilnych za pomocą static_cast
Stronę tą wyświetlono już: 184 razy
Funkcja szablonowa static_cast umożliwia rzutowanie kompatybilnych typów danych (np. int na double) jak również kompatybilnych typów wskaźnikowych. Przy czym ten drugi rodzaj rzutowania nie sprawdza poprawności typu w przypadku rzutowania w dół. Z tego powodu wszędzie tam, gdzie programista wie, że wskaźnik na klasę bazową jest dziedziczony przez z góry znany typ klasy można stosować rzutowanie za pomocą funkcji static_cast, w przeciwnym przypadku konieczne jest użycie funkcji dynamic_cast.
Oto prosty przykład:
- #include <iostream>
- class Base{
- public:
- virtual void fu() = 0;
- void baseFu() { std::cout << "baseFu is called" << std::endl; }
- };
- class ConcreteA : public Base{
- int k;
- public:
- ConcreteA() { k = 100; }
- virtual void fu() { std::cout << "fu from ConcreteA is called" << std::endl; }
- void concreteAfu() { std::cout << "concreteAfu is called " << k << std::endl; }
- };
- class ConcreteB : public Base{
- float k;
- public:
- ConcreteB() { k = 200; }
- virtual void fu() { std::cout << "fu from ConcreteB is called" << std::endl; }
- void concreteBfu() { std::cout << "concreteBfu is called " << k << std::endl; }
- };
- int main(){
- Base *base = new ConcreteA;
- ConcreteA* concreteA = static_cast<ConcreteA*>(base);
- concreteA->concreteAfu();
- base->fu();
- // to rzutowanie nie jest poprawne bo za base nie stoi wskaźnik na obiekt klasy ConcreteB
- ConcreteB* concreteB = static_cast<ConcreteB*>(base);
- concreteB->concreteBfu(); // z powodzeniem wywoła metodę concreteBfu ale zmienna k nie zostanie poprawnie wyświetlona
- std::cin.get();
- return 0;
- }
Wynik działania powyższego kodu będzie następujący:
concreteAfu is called 100 fu from ConcreteA is called concreteBfu is called 1.4013e-043
Wynika z tego niezbicie, że w przypadku gdy za wskaźnikiem na klasę bazową nie stoi obiekt klasy, na którą odbywa się rzutowanie, wtedy (chociaż samo rzutowanie się powiedzie) uzyskany wskaźnik na obiekt nie będzie zawierał wskaźnika na poprawnie zainicjalizowany obiekt klasy, na który rzutowanie się odbywa.
W przypadku rzutowania typu zmiennoprzecinkowego na całkowity część ułamkowa jest ucinana:
- double k1 = 10.234, k2 = -10.234;
- std::cout << "Rzutowanie dodatniej zmienoprzecinkowej na calkowita: " << static_cast<int>(k1) << std::endl;
- std::cout << "Rzutowanie ujemnej zmienoprzecinkowej na calkowita: " << static_cast<int>(k2) << std::endl;
Wynik powyższego kodu:
Rzutowanie dodatniej zmienoprzecinkowej na calkowita: 10 Rzutowanie ujemnej zmienoprzecinkowej na calkowita: -10