2012-07-25 22 views
7

Co sprawia, że ​​tenCzy naprawdę powinienem używać static_cast za każdym razem, gdy chcę dokonać konwersji między typami pierwotnymi?

long l = 1; 
char c = static_cast<char>(l); 

float f = 1.0f; 
int i = static_cast<int>(f); 

lepiej niż ten

long l = 1; 
char c = (char)l; 

float f = 1.0f; 
int i = (int)f; 

podczas rzucania jeden prymitywny typ danych do innego?

Mam dużo starego kodu, który używa drugiego stylu do odlewania w podobnych sytuacjach, więc jest to również pytanie, czy powinienem, czy nie, wykonać pełną wersję tego kodu.

+2

Możesz znaleźć [odpowiedź Bjarne Stroustrupa] (http://stroustrup.com/bs_faq2.html#static-cast) dobrą lekturę. – chris

Odpowiedz

21

Przyszłe zabezpieczenia.

Powiedzmy w przyszłości zrobić to:

float blah = 1.0f; 
float* f = &blah; 

Teraz int i = static_cast<int>(f); przystanki kompilacji, ale int i = (int)f; robi reinterpret_cast.

static_cast<int> to to jest dokładnie to, co chcę zrobić. (int) jest zrobić, co możesz, aby uzyskać int. W tym ostatnim kompilator zrobi wszystko, aby uzyskać wartość int, a to rzadko (nigdy?) Pożądane.

+0

Niezbyt pożądane, ale tak się dzieje. Na przykład jeden z możliwych zwrotów z [tej funkcji] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633585 (v = vs.85) .aspx) jest wskaźnikiem funkcji. Typ powrotu funkcji to 'long' lub' __int64'. – chris

+0

@chris Och, to dziwne. Ale "reinterpret_cast" i tak by działało dobrze. –

+0

Rzeczywiście. Większość api pochodzi prosto z C i używają wszelkiego rodzaju "hacki", aby zrobić to, czego potrzebują. – chris

1

Problem związany z obsadami w stylu C polega na tym, że możesz wykonywać konwersje, których nie zamierzałeś.

Jest to coś, co powinieneś zrobić w przyszłości, ale nie wrócę i nie zmienię go, chyba że znajdziesz jakiś problem.

6

Tak, powinieneś.

Odlewy są głównym źródłem błędów. Są to sposoby wokół systemu typów, który jest jednym z najlepszych łapaczy błędów dostępnych dla programistów.

Strumień static_cast jest znacznie bardziej widoczny i o wiele bardziej specyficzny niż stary rzut w stylu c. Chcesz, żeby się wyróżniały. Chcesz, żeby były oczywiste podczas debugowania. Chcesz, żeby przyszły programista zrozumiał, dlaczego to robisz.

To, że trudniej jest wpisać static_cast<blah>(foo), jest również korzystne, ponieważ zachęca do rzutowania tylko wtedy, gdy jest to absolutnie konieczne.

8

The za każdym razem jest trochę wskazania.

Nie należy konwertować między typami pierwotnymi tak często, że wpisywanie kilku dodatkowych znaków za każdym razem jest zbyt uciążliwym zadaniem. To trochę tak, jakbyś narzekał, że musisz nosić kask za każdym razem, gdy wykonujesz jakąś niebezpieczną czynność. Jeśli uważasz, że noszenie kasku jest zbyt denerwujące, to problem polega raczej na tym, że angażujesz się w niebezpieczną aktywność zbyt często, niż wymaga tego kask.

Jeśli chodzi o adresowanie starszego kodu, możesz sprawdzić numer this question, aby uzyskać odpowiedzi (w tym moje własne).

2

Odlew konstruktora jest alternatywą. Zakładając, że zdefiniowano konstruktor konwersji.Na przykład:

int i(0); 
float f(3.14F); 
i = int(f); 

Należy jednak zdecydowanie wolę static_cast i inne C++ rzuca na gipsie C stylu jak te w zasadzie powiedzieć „try każdą obsadę aż coś działa”, który będzie ostatecznie uderzyć odpowiednik reinterpret_cast i prawdopodobnie dać niewłaściwe zachowanie.

+1

"Konstruktor rzutów AFAIK" jest odpowiednikiem rzutowania w stylu c. –

+0

Jest to prawdopodobnie * trochę * bardziej bezpieczny typ, ale tak, pojawiłby się ten sam problem podczas wprowadzania wskaźników. Idealnym rozwiązaniem oczywiście nie jest rzucanie w ogóle i po prostu stosowanie właściwych typów. – AJG85

+0

Kiedy mówię równoważny, mam na myśli. 5.2.3 pkt 1: Prosty specyfikator typu (7.1.6.2) lub specyfikator typu nazwy (14.6), po którym następuje rodzicielska lista-wyrażeń, konstruuje wartość określonego typu, podaną w wykazie wyrażeń. Jeśli lista wyrażeń jest pojedynczym wyrażeniem, wyrażenie konwersji typu jest równoważne (w definicji i jeśli jest zdefiniowane w znaczeniu) z odpowiednim wyrażeniem rzutowania (5.4). –