2016-02-18 11 views
9

Zdaję sobie sprawę, że różne podmioty odlewania w C++ zostały już omówione tutaj wiele razy, ale moje pytanie brzmi konkretnie o wylewanej między typów liczbowych, a nie o ogólnych różnic między C styl i C++ operatorzy stylu. Uważam to za zupełnie inny temat niż rzucanie w hierarchii klasowej.C++ odlewania pomiędzy typami numerycznymi

że chcę oddać int i do podwójne, niektóre opcje mam są

static_cast<double>(i) 
(double) i 
double(i) 

Osobiście preferuję styl konstruktora-like w 3 linii w tym przypadku, ponieważ chciałbym wyrazić że nie jest to rodzaj klasy, w którym na pewno będę używał static_cast lub dynamic_cast.

Z wyjątkiem tego, że trudno jest znaleźć ten typ obsady podczas wyszukiwania w edytorze tekstu, czy są jakieś wady z mojego wyboru?

+1

Jaki jest kontekst? Dlaczego musisz rzucać? –

+0

@Karoly Horvath: Dobre pytanie, zawsze staram się unikać rzutów, ale typowe przypadki, w których to robię, są zawarte w obliczeniach lub podczas przekazywania argumentów funkcji. –

+4

"Trudno znaleźć ten typ obsady" jest wystarczającym powodem, aby nigdy z niego nie korzystać. –

Odpowiedz

4

static_cast<double>(i) jest z pewnością najjaśniejszym wyrazem waszego zamiaru w tym konkretnym przypadku.

Podczas rzucania pomiędzy typami liczbowymi często jesteś rzut kamieniem od niezdefiniowanego zachowania. Bądź więc ostrożny w ogóle. Chociaż rzutowanie jest zdefiniowane dla każdej możliwej wartości i, rzutowanie double na może przepełnić int, a to zachowanie jest niezdefiniowane w C++.

Zawsze radzę sprawdzić, czy typ miejsca docelowego może uwzględniać typ źródła. std::numeric_limits<>::max() itp. Mogą pomóc tutaj.

Standard C++ nie określa maksymalnego rozmiaru int (mimo że uzupełnienia 16, 32 i 64 bit 2 są wspólne), więc potencjalnie może nie być reprezentowany jako double.

W moim kodu mam nazw zawierający

template< 
     typename T/*the desired type*/, 
     typename/*the source type*/ Y 
    > T integral_cast(const Y& y) 
    { 
     static_assert(false, "undefined integral_cast"); 
    } 

które specjalizują się dla każdej obsady numerycznej muszę.

+2

'static_cast' nie będzie tu bronić przed niezdefiniowanym zachowaniem. I PO dał bardzo dobry punkt dla ich preferowanej obsady w tym konkretnym przypadku. – StoryTeller

+0

Rzeczywiście, ale jest to bardzo przejrzysty sposób zapisu. Należy jednak pamiętać, że rzutowanie z 'int' na' double' jest * zawsze * zdefiniowane. – Bathsheba

+0

To jest oparte na opiniach. To zdecydowanie wyróżnia się bardziej, ale pojęcie budowy "podwójnego" z "int" jest również bardzo jasne. – StoryTeller

3

Jedną z głównych wad tych podejść jest to, że obsada nie jest bezpieczna przed przepełnieniami i innymi błędami numerycznymi.

Używanie jest natychmiastowym rozwiązaniem praktycznym i ta metoda nie jest oznaczona przez narzędzia analityków statycznych, takie jak PVS studio. podejście (double)i generuje ostrzeżenie.

Prawdopodobnie najbezpieczniejszym rozwiązaniem jest mieć własną obsadę powiedzmy numeric_cast<T>()

template <class OT, class ST> 
OT numeric_cast(const ST value) 
{ 
    return static_cast<OT>(value); 
} 

Zaletą tej funkcji jest to, że można zrobić związanych czeków i innych kontroli numerycznej aby zapewnić, że obsada jest uzasadniony i nie zwracaj (lub otrzymuj) niepotrzebne wartości.

Istnieje inny sposób radzenia sobie z liczbami, ale działa on tylko ze stałymi wartościami czasu kompilacji. Dla tego sprawdzenia user defined string literals