Typová konverze ( typizace , donucení ) - v informatice převod hodnoty jednoho typu na hodnotu jiného typu .
Existují typy obsazení:
Explicitní přetypování specifikuje programátor v textu programu pomocí:
Implicitní přetypování provádí překladatel ( překladač nebo tlumočník ) podle pravidel popsaných v jazykové normě. Většina jazykových standardů zakazuje implicitní převody.
Ve slabě typovaných objektově orientovaných jazycích, jako je C++ , je mechanismus dědičnosti implementován přetypováním typu ukazatele na aktuální objekt do základní třídy (v typově bezpečných jazycích , jako je OCaml , koncept přetypování typu v podstatě chybí a přípustnost odkazování na komponentu podtypu je řízena typy mechanismu kontroly konzistence v době kompilace a přímý přístup zůstává ve strojovém kódu).
K implicitnímu přetypování dochází v následujících případech [1] :
Například při provádění binární aritmetické operace jsou hodnoty operandů přetypovány na stejný typ. Při dědění jsou ukazatele odvozené třídy přetypovány na ukazatele základní třídy.
Zvažte příklad v jazyce C.
dvojité d ; // skutečný typ long l ; // typ celého čísla int i ; // celočíselný typ if ( d > i ) d = i ; if ( i > l ) l = i ; if ( d == l ) d *= 2 ;Při provádění porovnávacích operací a při přiřazování jsou proměnné různých typů implicitně přetypovány na stejný typ.
Implicitní konverze mohou mít vedlejší účinky. Například při přetypování čísla reálného typu na celočíselný typ se zlomková část ořízne ( zaokrouhlování se neprovádí) [2] . Zpětný převod může snížit přesnost kvůli rozdílům v reprezentaci reálných a celých čísel. Například v proměnné typu ( IEEE 754 s jednoduchou přesností číslo s plovoucí desetinnou čárkou ) nemůžete uložit číslo 16 777 217 bez ztráty přesnosti, ale můžete do proměnné typu 32bitové celé číslo. Kvůli ztrátě přesnosti mohou porovnávací operace stejného čísla reprezentovaného celočíselným a reálným typem (například a ) dávat falešné výsledky (čísla se nemusí rovnat). float intintfloat
#include <stdio.h> int main ( void ) { int i_value = 16777217 ; float f_value = 16777216.0 ; printf ( "Celé číslo je:%d \n " , i_hodnota ); printf ( "Plovák je: %f \n " , f_value ); printf ( "Jejich rovnost:%d \n " , i_hodnota == f_hodnota ); }Výše uvedený kód vypíše následující, pokud je velikost 32 bitů a kompilátor podporuje standard IEEE 754 : int
Celé číslo je: 16777217 Plovák je: 16777216,000000 Jejich rovnost: 1Pro explicitní přetypování je název typu uveden v závorkách před proměnnou nebo výrazem. Zvažte příklad.
int X ; int Y = 200 ; char C = 30 ; X = ( int ) C * 10 + Y ; // Proměnná C je přetypována na typ intPro vyhodnocení posledního výrazu kompilátor provede něco takového:
I tak jsou možné chyby. Typ může být buď podepsaný ( ) nebo nepodepsaný ( ); výsledek závisí na implementaci kompilátoru a toto chování je standardem povoleno. Hodnota nepodepsaného typu při převodu na podepsaný typ se může ukázat jako záporná kvůli implementaci strojových instrukcí na některých procesorech . Aby se předešlo nejednoznačnostem, doporučuje se explicitně specifikovat signaturu pro typ . charsigned charunsigned charcharintchar
V C++ existuje pět explicitních operátorů konverze typů . První operace, závorky ( ), je podporována, aby byla zachována kompatibilita s C . Zbývající čtyři operace jsou zapsány jako (type_to)expression_from
xxx_cast < type_to >( expression_from )Zvažte příklad.
y = static_cast < podepsaná zkratka > ( 65534 ); // proměnná y bude nastavena na -2Těžkopádná klíčová slova jsou pro programátora připomínkou toho, že přetypování je plné problémů.
Operace static_castÚčel: Platné obsazení.
Operace je podobná operaci závorek s jednou výjimkou: nepřetypuje ukazatele na nesouvisející typy (k tomu se používá operace ). static_castreinterpret_cast
Aplikace:
Omezení na expression_from: ne.
Omezení na type_to: Musí existovat způsob, jak převést hodnotu výrazu expression_fromna typ type_to, using operator type_tonebo konstruktor.
Vytváří operace kód: Obecně ano (například volání přetíženého přetypování nebo operace konstruktoru). static_cast
Zdroje logických chyb: závisí na tom, co budete s operací dělat. Jsou možné přetečení, mimo rozsah a dokonce (pro převod ukazatelů) poškození paměti.
Příklady.
// Získejte procento zásahu. dvojité sklopné procento ( const int aHitCount , // počet zásahů const int aShotCount // počet výstřelů ) { if ( aShotCount == 0 ) return 0.0 ; // Casting to double se provádí za účelem provedení skutečného (neceločíselného) dělení return static_cast < double > ( aHitCount * 100 ) / static_cast < double > ( aShotCount ); } // následující řádky jsou ekvivalentní // pomocí operace static_cast string s = static_cast < string > ( "Ahoj!" ); // volání konstruktoru s jedním argumentem string s = string ( "Ahoj!" ); // pomocí operace v závorkách string s = ( string ) "Ahoj!" ; string s = static_cast < string > ( 5 ); // nezkompiluje, kompilátor nemůže najít vhodný konstruktor Operace dynamic_castÚčel: seřazení hierarchie dědičnosti se zvláštním chováním, pokud objekt není požadovaného typu.
Operace získá informace o typu objektu expression_frompomocí RTTI . Pokud je typ type_tonebo jeho podtyp, přetypování se provede. V opačném případě:
Omezení na expression_from: Výraz musí být odkazem nebo ukazatelem na objekt, který má alespoň jednu virtuální funkci .
Omezení na type_to: odkaz nebo ukazatel na potomka expression_fromtypu.
Generuje operace kód: ano. dynamic_cast
Logické chyby jsou možné, pokud operace předá argument, který nemá typ type_toa nekontroluje rovnost ukazatele (respektive nezpracovává výjimku ). NULLstd::bad_cast
Operace const_castÚčel: odstranění/instalace modifikátoru(ů) a /nebo . Často se to používá k překonání špatné architektury programu nebo knihovny, k dokování C s C++, k předávání informací přes generické ukazatele , k současnému psaní konstantní a nekonstové verze funkce [3] ( existuje bypass v C++14 [3] ). constvolatilemutablevoid*decltype(auto)
Omezení na expression_from: Výraz musí vracet odkaz nebo ukazatel.
Omezení na type_to: typ se musí shodovat s type_totypem výrazu expression_fromaž do modifikátorů a .constvolatilemutable
Generuje operace kód: no. const_cast
Zdroje logických chyb: Program může upravit neměnný objekt. Někdy to může vést k poruše segmentace , někdy podprogram nemůže očekávat [3] , že se paměť, kterou má k dispozici pro čtení, náhle změnila.
Zvažte například kód dynamické knihovny .
#include <řetězec> // řetězec pomocí jmenného prostoru std ; jmenný prostor { string s = "Wikipedie" ; // Globální proměnná // metoda string::c_str() vrací ukazatel typu const char * } typedef char * PChar ; void __declspec ( dllexport ) WINAPI SomeDllFunction ( PChar & rMessage ) { // převod char const * na char * rMessage = const_cast < char * > ( s . c_str () ); }Když je knihovna načtena do paměti procesu , vytvoří se nový datový segment, který obsahuje globální proměnné. Kód funkce je umístěn v knihovně a při volání vrací ukazatel na skrytý člen objektu globální třídy . Operace se používá k odstranění modifikátoru . SomeDllFunction()stringconst_castconst
Operace reinterpret_castPřiřazení: Psací hříčka - Přiřazení jiného typu (ne nutně kompatibilního s daným) do paměťového místa při zachování bitové reprezentace.
S objektem vráceným výrazem expression_fromse zachází jako s objektem typu type_to.
Omezení na expression_from: Výraz musí vracet hodnotu ordinálního typu (libovolné celé číslo, booleovské číslo nebo enum ), ukazatel nebo odkaz. boolenum
Omezení na type_to:
Generuje operace kód: no. reinterpret_cast
Zdroje logických chyb. Objekt vrácený výrazem expression_fromnemusí být typu type_to. Nejde to nijak zkontrolovat, plnou zodpovědnost za správnost převodu přebírá programátor.
Zvažte příklady.
// Vrátí hodnotu true, pokud je x konečné. // Vrátí false, pokud číslo x je ∞ nebo NaN. bool isfinite ( double const x ) { // konverze double const -> uint64_t const & uint64_t const & y = reinterpret_cast < uint64_t const & > ( x ); return ( ( y & UINT64_C ( 0x7FF0000000000000 ) ) != UINT64_C ( 0x7FF0000000000000 ) ); } // pokus o získání adresy dočasné hodnoty long const & y = reinterpret_cast < long const & > ( x + 5.0 ); // chyba: výraz x + 5.0 není odkaz