rzutowanie




[ 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?00
T3 Przetwarzanie rzutowe
rzutowanie aksonometryczne
3 Rzutowanie prostokatne
Rzutowanie
01 RZUTOWANIEid)30
1 2wykr 6 rzutów prost
Europejska metoda rzutowania
Gwirt rzutowanie 2
C w7 tablice wielowym rzutowanie
16 opracowanie rzutowanie metoda najmniejszych kwadratow
rzutowanie bryl
13 PRZENIESIENIE WSKAZNIKW KONSTRUKCYJNYCH METODA BEZPOSREDNIEGO RZUTOWANIA, DOKLADNOSC
Rzutowanie Prostokątne
Rzutowe afiniczne i euklidesowe twierdzenia o stożkowych

więcej podobnych podstron