Rzutowanie typów kompatybilnych za pomocą static_cast

Stronę tą wyświetlono już: 58 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:

Listing 1
  1. #include <iostream>
  2. class Base{
  3. public:
  4. virtual void fu() = 0;
  5. void baseFu() { std::cout << "baseFu is called" << std::endl; }
  6. };
  7. class ConcreteA : public Base{
  8. int k;
  9. public:
  10. ConcreteA() { k = 100; }
  11. virtual void fu() { std::cout << "fu from ConcreteA is called" << std::endl; }
  12. void concreteAfu() { std::cout << "concreteAfu is called " << k << std::endl; }
  13. };
  14. class ConcreteB : public Base{
  15. float k;
  16. public:
  17. ConcreteB() { k = 200; }
  18. virtual void fu() { std::cout << "fu from ConcreteB is called" << std::endl; }
  19. void concreteBfu() { std::cout << "concreteBfu is called " << k << std::endl; }
  20. };
  21. int main(){
  22. Base *base = new ConcreteA;
  23. ConcreteA* concreteA = static_cast<ConcreteA*>(base);
  24. concreteA->concreteAfu();
  25. base->fu();
  26. // to rzutowanie nie jest poprawne bo za base nie stoi wskaźnik na obiekt klasy ConcreteB
  27. ConcreteB* concreteB = static_cast<ConcreteB*>(base);
  28. concreteB->concreteBfu(); // z powodzeniem wywoła metodę concreteBfu ale zmienna k nie zostanie poprawnie wyświetlona
  29. std::cin.get();
  30. return 0;
  31. }

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:

Listing 2
  1. double k1 = 10.234, k2 = -10.234;
  2. std::cout << "Rzutowanie dodatniej zmienoprzecinkowej na calkowita: " << static_cast<int>(k1) << std::endl;
  3. 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

Komentarze