[ Code Zone ] - Serwis programistyczny - C/C++
Strona główna
| Język C++ | C++
Builder | Programy
| Narzędzia
| Forum | Księga
gości | Sznurki | Kontakt
Konwersja wartości (rzutowanie)
Aby było możliwe przypisanie wartości do zmiennej
typy obu danych muszą być identyczne lub kompatybilne. Próba
przypisania innego typu wiąże się często z utratą wartości lub ze
zwróceniem błędu konwersji przez kompilator. Jeśli przypiszemy
liczbę zmiennoprzecinkową do zmiennej typu int kompilator
może zasygnalizować nam ostrzeżeniem, że część danych może zostać
utracona. Ale jeśli akurat chcemy właśnie pozbyć się części po
przecinku i przeprowadziliśmy tę operację rozmyślnie? Wtedy musimy
urzyć rzutowania. W C++ istnieją dwie postacie tej operacji:
typ (wartość)
oraz
(typ) wartość
i oba zwracają wartość po konwersji wyrażenia do
naszego typu. Rzutując typy wskaźnikowe nalezy korzystać z drugiego
sposobu.
Wracając do naszego przypadku, aby rozwiązać problem
przypisania float do int, musimy zrzutować liczbę
zmiennoprzecinkową do całkowitej:
float liczba1 = 3.14;int liczba2 =
int(liczba1);
Teraz przejdźmy do nieco bardziej skomplikowanych
przypadków. Jeśli chcemy podzielić dwie liczby całkowite i w wyniku
otrzymać ułamek, musimy skorzystać z rzutowania. Nie wystarczy tu ot
tak sobie skonwertować wynik dzielenia np.
float rezultat = float( 10 / 3 );
Otrzymamy tutaj 3 bez części ułamkowej zamiast 3 i
1/3, gdyż wynik dzielenia całkowitoliczbowego będzie - dla
kompilatora - zawsze liczbą całkowitą. Należy zrzutować jedną z
wartości przyjmowanych przez operator dzielenia np. dzielną:
float rezultat = (float)10 / 3;
Rzutowanie wskaźników
Jak dobrze wiemy, wskaźniki
w C++ mogą oznaczać praktycznie na wszystko. Jak także zapewne
wiesz, przechowują adres w pamięci, który jest - a jakże inaczej -
wartością liczbową. Dlatego też możemy rzutować typy wskaźnikowe na
wszystkie inne typy wskaźnikowe.
int Liczba = 1;void * pAdres =
(void *) &Liczba; // konwertujemy adres
zmiennej do typu void *int * pLiczba = (int *)
pAdres; // konwertujemy z powrotem adres na
wskaźnik typu int*pLiczba = 5; // i
modyfikujemy wartość zmiennej pod wskaźnikiem, w efekcie Liczba =
5
Przy rzutowaniu wskaźników należy uważać, gdyż nawet
w przypadku konwersji całkowicie niekompatybilnych typów kompilator
nie zwróci błędu. Dla niego rzutujemy adres na adres, czyli liczbę
na liczbę i pozornie nic w tym złego. Dzieje się tak do momentu, gdy
nie odwołamy się do danych przechowywanych przez wskaźnik. Wtedy
ukaże się nam uroczy i jakże lubiany komunikat w stylu "Access
Violation" :)
Specjalne rodzaje rzutowania
Wraz z C++ dostarczono także nowe sposoby rzutowania
dynamic_cast, reinterpret_cast oraz const_cast.
Mają one zwiększyć bezpieczeństwo przy rzutowaniu typów
wskaźnikowych.
dynamic_cast
Rzutowanie dynamiczne korzysta z tablicy RTTI
zawierającej informacje o typach danych i zwraca NULL, gdy konwersja
jest niemożliwa. Jest to rozwiązanie bezpieczniejsze od
standardowego rzutowania, gdyż można nie dopuścić do wykonywania
kodu, gdy konwersja nie powiedzie się. W środowisku C++ Builder jest
powszechnie zalecanym sposobem wyciągania informacji o komponencie,
który wywołal zdarzenie. Poniższa procedura obsługuje zdarzenie
kliknięcia pochodzące od wielu kontrolek typu TButton i TLabel.
void __fastcall
TForm1::Kliknieto(TObject *Sender){ TButton * pButton
= dynamic_cast<TButton*> (Sender); TLabel *
pLabel = dynamic_cast<TLabel*> (Sender);
if (pButton) pButton->Caption =
"Kliknąłeś na tym przycisku"; else if
(pLabel) pLabel->Caption = "Kliknąłeś na tej
etykiecie";}
Jeśli zdarzenie wywoła komponent innego typu niż
TButton lub TLabel, wynikiem obu rzutowań będzie NULL i nie zostanie
wykonana żadna akcja.
reinterpret_cast i const_cast
Dwa pozostałe rodzaje rzutowania są używane bardzo
rzadko i zapewne nigdy nie będziesz musiał ich stosować. Pierwszy
różni się od dynamic_cast możliwością poruszania się w dół i
w bok w hierarchi dziedziczenia (np. komponentów). Drugi umożliwia
rzutowanie ze wskaźnika zwykłego na wskaźnik stały i na odwrót.
Ewentualne pytania proszę zgłaszać na forum.
WhiteRAVEN,
4.11.2001
Wyszukiwarka
Podobne podstrony:
09 rzutowanie wwwid?00T3 Przetwarzanie rzutowerzutowanie aksonometryczne3 Rzutowanie prostokatneRzutowanie01 RZUTOWANIEid)301 2wykr 6 rzutów prostEuropejska metoda rzutowaniaGwirt rzutowanie 2C w7 tablice wielowym rzutowanie16 opracowanie rzutowanie metoda najmniejszych kwadratowrzutowanie bryl13 PRZENIESIENIE WSKAZNIKW KONSTRUKCYJNYCH METODA BEZPOSREDNIEGO RZUTOWANIA, DOKLADNOSCRzutowanie ProstokątneRzutowe afiniczne i euklidesowe twierdzenia o stożkowychwięcej podobnych podstron