Różne typy rzutowań w c++.

0

Witam.
Czy ktoś byłby w stanie na chłopski rozum wytłumaczyć poszczególne rzutowania: static_cast, dynamic_cast, reinterpret_cast, const_cast
Jeśli powiedzmy na rozmowie kwalifikacyjnej mielibyście pytanie o te rzutowania to jak byście odpowiedzieli?
Z góry dziękuję za odpowiedzi. Pozdrawiam.

0

static_cast, dynamic_cast, reinterpret_cast, const_cast

· static_cast jest zbędny bo za dużo pisania i brzydko wygląda, zwykłe rzutowanie w nawiasie jest krótsze,
· dynamic_cast rzadko się przydaje
· reinterpret_cast to zuo ale czasami konieczne
· const_cast takoż

tak naprawdę powyższe rzutowania nie są konieczne, bo wystarczy c-style cast który zależnie od kontekstu użycia robi to co jedno z powyższych, ale warto czasami podkreślić intencję programisty, zwłaszcza jeśli chodzi o const i reinterpret_cast.

0

reinterpret_cast - > handle do objektu i w drugą stronę.
const_cast -> np. const Dupa* na Dupa* i w drugąstronę.
dynamic_cast -> Base -> Derived i w drugą (ale nie zawsze).
static_cast -> unsigned do double etc.

1
pylaochos napisał(a):

reinterpret_cast - > handle do objektu i w drugą stronę.

Coś tu się pospieszyłeś.
reinterpret_cast traktuje przekazany obiekt jako coś zupełnie innego. Np:

 
int i = 10;
std::string str = reinterpret_cast<std::string>(i);

Efektem nie będzie oczywiście zamiana inta na string, ale tego, co znajduje się w pamięci, na którą wskazuje zmienna i. Efektem tego będzie, że string będzie zawierał znak o kodzie ASCII 10. W najlepszym wypadku (jeśli w pamięci za zmienną i znajduje się znak 0). W najgorszym (zazwyczaj) będzie zawierał mnóstwo śmieci. Dalsze działanie w takim wypadku nie jest zdefiniowane i prowadzi do wywałek. Także reinterpret_cast używaj tylko wtedy, kiedy masz pewność, że jeden obiekt można zamienić na drugi.

Przykład:
Klasa MySuperString
Posiada metodę GetBuffer():

 
const * MySuperChar GetBuffer() const;

Ty chcesz z tego zrobić std::wstring, ale do tego potrzebujesz **wchar_t ***, a nie **MySuperChar ***
Jeśli więc masz pewność, że MySuperChar jest tak samo zbudowany jak wchar_t, możesz zrobić tak:

 
std::wstring str = reinterpret_cast<const wchar_t *>(mss.GetBuffer());

dynamic_cast -> Base -> Derived i w drugą (ale nie zawsze).

Zawsze z Derived do Base ;)
Ale nie zawsze z Base do Derived (jeśli rzutujesz na klasę, która nie pochodzi od Base to dostaniesz NULL lub wyjątek, w zależności, czy rzutujesz wskaźnik, czy referencję)

0
Juhas napisał(a):
pylaochos napisał(a):

reinterpret_cast - > handle do objektu i w drugą stronę.

Coś tu się pospieszyłeś.
reinterpret_cast traktuje przekazany obiekt jako coś zupełnie innego. Np:

 
int i = 10;
std::string str = reinterpret_cast<std::string>(i);

yyy...

 
Class* object = new Class();
unsigned int ptrAsInteger = reinterpet_cast<unsigned int>(object);

potem:

 
Class* object = reinterpet_cast<Class*>(ptrAsInteger );

To jest przykład użycia: handle. To czy pamiętasz jaki to był naprawdę typ czy nie (i powodujesz mazanie po pamięci) to osobna kwestia ;), polecam przechowywać gdzieś std::type_info.

Juhas napisał(a):

Efektem nie będzie oczywiście zamiana

yyyy nie. Nic nie będzie "zamieniane". Po prostu obszar pamięci określony przez ten operator będzie traktowany jak by zawierała obiekt na który rzutujemy.

Juhas napisał(a):

inta na string, ale tego, co znajduje się w pamięci, na którą wskazuje zmienna i. Efektem tego będzie, że string będzie zawierał znak o kodzie ASCII 10. W najlepszym wypadku (jeśli w pamięci za zmienną i znajduje się znak 0). W najgorszym (zazwyczaj) będzie zawierał mnóstwo śmieci. Dalsze działanie w takim wypadku nie jest zdefiniowane i prowadzi do wywałek. Także reinterpret_cast używaj tylko wtedy, kiedy masz pewność, że jeden obiekt można zamienić na drugi.

Przykład:
Klasa MySuperString
Posiada metodę GetBuffer():

 
const * MySuperChar GetBuffer() const;

Ty chcesz z tego zrobić std::wstring, ale do tego potrzebujesz **wchar_t ***, a nie **MySuperChar ***
Jeśli więc masz pewność, że MySuperChar jest tak samo zbudowany jak wchar_t, możesz zrobić tak:

 
std::wstring str = reinterpret_cast<const wchar_t *>(mss.GetBuffer());

dynamic_cast -> Base -> Derived i w drugą (ale nie zawsze).

Zawsze z Derived do Base ;)
Ale nie zawsze z Base do Derived (jeśli rzutujesz na klasę, która nie pochodzi od Base to dostaniesz NULL lub wyjątek, w zależności, czy rzutujesz wskaźnik, czy referencję)

Racja, pomyliłem się :)

3
Juhas napisał(a):
pylaochos napisał(a):

reinterpret_cast - > handle do objektu i w drugą stronę.

Coś tu się pospieszyłeś.
reinterpret_cast traktuje przekazany obiekt jako coś zupełnie innego. Np:

 
int i = 10;
std::string str = reinterpret_cast<std::string>(i);

Efektem nie będzie oczywiście zamiana inta na string, ale tego, co znajduje się w pamięci, na którą wskazuje zmienna i. Efektem tego będzie, że string będzie zawierał znak o kodzie ASCII 10.

Nie, to się nie skompiluje. http://melpon.org/wandbox/permlink/5SLOg1QW4JVH6UVI

Polecam spróbować kod zanim się z pewnością o nim wypowiadasz.

pylaochos napisał(a):

reinterpret_cast - > handle do objektu i w drugą stronę.
const_cast -> np. const Dupa* na Dupa* i w drugąstronę.
dynamic_cast -> Base -> Derived i w drugą (ale nie zawsze).
static_cast -> unsigned do double etc.

static_castjak najbardziej może służyć do rzutowania Base ⟶ Derived jeśli nie chcesz płacić za dynamic_cast a masz pewność, że robisz dobrze.

0

To jest przykład użycia: handle. To czy pamiętasz jaki to był naprawdę typ czy nie (i powodujesz mazanie po pamięci) to osobna kwestia ;), polecam przechowywać gdzieś std::type_info.

To nie jest żaden handle, tylko adres do obiektu. Jako handle to rozumiem HANDLE z WinAPI.

Juhas napisał(a):

Efektem nie będzie oczywiście zamiana

yyyy nie. Nic nie będzie "zamieniane". Po prostu obszar pamięci określony przez ten operator będzie traktowany jak by zawierała obiekt na który rzutujemy.
</quote>

No to przecież napisałem, że NIE będzie zamiana...

0
kq napisał(a):
Juhas napisał(a):
pylaochos napisał(a):

reinterpret_cast - > handle do objektu i w drugą stronę.

Coś tu się pospieszyłeś.
reinterpret_cast traktuje przekazany obiekt jako coś zupełnie innego. Np:

 
int i = 10;
std::string str = reinterpret_cast<std::string>(i);

Efektem nie będzie oczywiście zamiana inta na string, ale tego, co znajduje się w pamięci, na którą wskazuje zmienna i. Efektem tego będzie, że string będzie zawierał znak o kodzie ASCII 10.

Nie, to się nie skompiluje. http://melpon.org/wandbox/permlink/5SLOg1QW4JVH6UVI

Racja, mój błąd. Powinien być wskaźnik na string.

0

Słyszałem też, że niektóre rzutowania są wykonywane w trakcie kompilacji, a niektóre w czasie działa programu. Czy ktoś może mi to wytłumaczyć co to znaczy? Bo wiem, że np. biblioteki mogą być dołączane w czasie kompilacji lub dopiero w czasie działania programu. Ale rzutowania?
I jeśli tak jest to które z rzutowań wyżej wymienionych są dokonywane w czasie kompilacji, a które w czasie działania programu?

0

Czy ktoś mógłby jak dla durnia wytłumaczyć co to znaczy, że rzutowanie jest wykonywane w czasie działania programu, a w czasie kompilacji? Niestety niezbyt długo zajmuję się programowaniem i ciężko mi zrozumieć taką dokumentacje, tym bardziej po angielsku. Jeśli ktoś jest bardzo cierpliwy to będę wdzięczny za wytłumaczenie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1