Systém typů C++ (Příručka programování moderních C++)
Pojem typu je velmi důležité v jazyce C++.Každé proměnné argument funkce a funkce vrátí hodnotu musí mít typ, chcete-li být zkompilována.Navíc každý výraz (včetně hodnoty literálů) je implicitně kompilátorem typu před vyhodnocením.Mezi typy patří int k uložení integrální hodnoty double k uložení hodnoty plovoucí desetinné čárky (označované také jako Skalární datových typů), nebo standardní knihovna tříd std::basic_string k uložení textu.Můžete vytvořit vlastní typ definováním class nebo struct.Typ určuje množství paměti, kterou chcete přidělit pro proměnné (nebo výsledek výrazu), druhy hodnot, které mohou být uložena v proměnné, způsob interpretace těchto hodnot (jako vzorky bit) a operace, které lze provádět v něm.Tento článek obsahuje přehled neformální hlavních funkcí systému typu C++.
Terminologie
Proměnné: symbolický název množství dat tak, aby název lze použít pro přístup k datům odkazuje v rámci rozsahu kódu, kde je definována.V jazyce C++ "proměnné" obecně slouží odkázat na výskyty skalární datové typy, že instance jiných typů se obvykle nazývají "objekty".
Objekt: kvůli jednoduchosti a přehlednosti v tomto článku používá termín "objekt" Chcete-li odkazovat na libovolnou instanci třídy nebo struktury a kdy se používá v obecném smyslu zahrnuje všechny typy i skalární proměnné.
Typ POD (obyčejný stará data): odkazuje tato neformální kategorie datové typy jazyka C++ jsou Skalární typy (viz část základní typy) nebo jsou tříd POD.Třída LUSKU má žádné statické datové členy, které nejsou také lusky a nemá žádné konstruktory definované uživatelem definované uživatelem destruktory a operátory přiřazení definované uživatelem.Navíc třída LUSKU má žádné virtuální funkce, žádné základní třídy a žádné dat nestatickou soukromé nebo chráněné členy.Typy LUSKU se často používají pro výměnu externích dat, například s modulem v jazyce C, (který má pouze typy LUSKU).
Určení typu proměnné a funkce
C++ je silného jazyk a je také staticky zadané; Každý objekt má typ a, zadejte nikdy změny (nikoli k záměně s statická data objects).
Pokud deklarujete proměnnou ve vašem kódu, musíte explicitně zadat jeho typ, nebo použít auto klíčové slovo na pokyn kompilátoru odvodit typ z je inicializace.
Pokud deklarujete funkce ve vašem kódu, je nutné zadat typ jednotlivých argumentů a její vrácená hodnota nebo void je-li vrácena žádná hodnota funkce.Výjimkou je při použití funkce šablony, které umožňují libovolné typy argumentů.
Po deklarování proměnné nelze změnit typ někdy později.Však můžete zkopírovat hodnotu proměnné nebo vrácené hodnoty funkce do jiné proměnné různého typu.Tyto operace jsou označovány jako převody typu, které jsou někdy nutné, ale jsou také potenciální zdroje ke ztrátě dat nebo nesprávnosti.
Při deklaraci proměnné typu LUSKU důrazně doporučujeme že inicializujete, což znamená, že mu přiřadit počáteční hodnotu.Dokud inicializovat proměnnou, má hodnotu "smetí", která se skládá z jakékoli bitů se stalo dříve nacházet v umístění v paměti.Toto je důležitým aspektem C++ mějte na paměti, zejména v případě, že pochází z jiného jazyka, který zpracovává inicializace pro vás.Při deklarování proměnné typu třídy bez LUSKŮ, zpracovává konstruktoru inicializace.
Následující příklad ukazuje některé jednoduché deklarace proměnných s některé popisy pro každou.Tento příklad také ukazuje, jak kompilátor používá informace o typu povolit nebo zakázat určité následné operace proměnné.
int result = 0; // Declare and initialize an integer.
double coefficient = 10.8; // Declare and initialize a floating
// point value.
auto name = "Lady G."; // Declare a variable and let compiler
// deduce the type.
auto address; // error. Compiler cannot deduce a type
// without an intializing value.
age = 12; // error. Variable declaration must
// specify a type or use auto!
result = "Kenny G."; // error. Can’t assign text to an int.
string result = "zero"; // error. Can’t redefine a variable with
// new type.
int maxValue; // Not recommended! maxValue contains
// garbage bits until it is initialized.
Základní typy (vestavěný)
Na rozdíl od některých jazyků C++ má žádné univerzální základní typ, z něhož jsou odvozeny všechny ostatní typy.Visual C++ Implementace jazyka obsahuje mnoho základní typy, označované také jako předdefinované typy.To zahrnuje číselné typy, jako je například int, double, long, bool, plus char a wchar_t typy znaků ASCII a UNICODE, respektive.Většina základních typů (s výjimkou bool, double, wchar_t a související typy) všechny obsahují nepodepsaná verze, které upravit rozsah hodnot, které můžete ukládat proměnné.Například int, který ukládá 32-bit signed integer, může představovat hodnotu od 648 do 2 147 483 647.unsigned int, Který je rovněž uložena jako 32bitů, můžete ukládat hodnoty od 0 do 4 294 967 295.Celkový počet možných hodnot v každém případě je stejný; pouze tato oblast se liší.
Základní typy jsou rozpoznávány kompilátoru, který má vestavěné pravidla, která určují, jaké operace lze provádět na jejich, a jak lze převést na jiné základní typy.Úplný seznam předdefinovaných typů a jejich velikost a číselné mezní hodnoty, naleznete v Základní typy (C++).
Následující ilustrace znázorňuje relativní velikosti předdefinované typy:
V následující tabulce jsou uvedeny nejčastěji používané základní typy:
Type |
Size |
Comment (Komentář) |
---|---|---|
int |
4 bajty |
Výchozí volba pro integrální hodnoty. |
double |
8 bajtů |
Výchozí volba pro hodnoty s plovoucí čárkou. |
bool |
1 bajt |
Představuje hodnoty, které mohou být buď PRAVDA nebo NEPRAVDA. |
char |
1 bajt |
Používá se pro znaky standardu ASCII v starší řetězce ve stylu C nebo std::string objekty, které nikdy nebudete muset převést do kódování UNICODE. |
wchar_t |
2 bajty |
Představuje hodnoty "širokou" znaků, které mohou být kódovány ve formátu UNICODE (UTF-16 v systému Windows, jiné operační systémy mohou lišit).Toto je typ znak, který je používán v řetězcích typu std::wstring. |
unsigned char |
1 bajt |
C++ obsahuje žádné integrované byte typu.Unsigned char slouží ke znázornění hodnotu bajtu. |
unsigned int |
4 bajty |
Výchozí volba pro bitové příznaky. |
dlouhé dlouhé |
8 bajtů |
Představuje velmi velké celočíselné hodnoty. |
Typu void.
void Typ je speciální typ; nelze deklarovat proměnnou typu void, ale můžete deklarovat proměnnou typu void * (ukazatel na void), což je někdy nezbytné při přidělování paměti raw (kontrakty).Nicméně ukazatele na void jsou není typově bezpečný a obecně jejich použití je v moderní C++ důrazně nedoporučuje.V deklaraci funkce void vrátit hodnota znamená, že funkce nevrátí hodnotu; To je běžné a přijatelné použití void.Zatímco funkce požadovaných jazyků C, které mají nulové parametry deklarovat void v seznamu parametrů, například fou(void), tento postup se nedoporučuje v moderní C++ a by měla být prohlášena za fou().Další informace naleznete v tématu Převody typu a typ bezpečnosti (C++).
Const typ kvalifikátoru
Všechny vestavěné nebo uživatelem definovaný typ může být kvalifikován klíčové slovo const.Kromě toho mohou být členské funkce const-kvalifikovaných a dokonce i const-přetížený.Hodnota const typu nelze změnit poté, co je inicializován.
const double PI = 3.1415;
PI = .75 //Error. Cannot modify const variable.
const Kvalifikátoru se velmi často používá v deklaraci funkce a proměnné a "const správnosti" je důležitou koncepcí v jazyce C++; v podstatě znamená použití const k zajištění v době kompilace neúmyslně měnit hodnoty nejsou.Další informace naleznete v tématu Const (C++).
A const typu se liší od jeho verze bez const; například const int je odlišný typ z int.Můžete použít v jazyce C++ const_cast operátor ojediněle ty musí po odebrání const strukturou z proměnné.Další informace naleznete v tématu Převody typu a typ bezpečnosti (C++).
Typy řetězců
Přesně řečeno jazyk C++ nemá vestavěné "řetězec" typ; chara wchar_t ukládat jednotlivé znaky – je třeba deklarovat pole těchto typů sblížit řetězec, přidání ukončující null hodnotu (například ASCII ‘\0’) na jeden prvek pole za poslední platný znak (také nazývané "C-řetězec ve stylu").Řetězce ve stylu C vyžaduje mnohem více kódu k zápisu nebo použití funkce knihovny řetězec externí nástroje.Ale v moderní C++ máme standardní knihovny typů std::string (pro 8-bit char-zadejte řetězce znaků) nebo std::wstring (pro 16bitové wchar_t-zadejte řetězce znaků).Protože jsou součástí standardní knihovny, které jsou zahrnuty v žádné vyhovující prostředí sestavení C++, lze tyto kontejnery STL představit jako typy nativní řetězec.Stačí použít #include <string> směrnice tak, aby tyto typy k dispozici v programu.(Používáte-li knihovny MFC nebo knihovny ATL, třída CString je také k dispozici, ale není součástí C++ standard.) Použití pole znaků ukončený znakem null (výše zmíněné řetězce ve stylu C) je v moderní C++ důrazně nedoporučuje.Další informace o rozhodnout, jaký typ řetězce pro použití v moderní program C++ a převod mezi různými druhy, viz Řetězce a Text (moderní C++).
Uživatelem definované typy
Při definování class, struct, union, nebo enum, tato konstrukce se používá ve zbývající části kódu, jako by šlo o základní typ.Má známé velikosti v paměti a určitá pravidla o způsobu jeho použití na něj vztahují ke kontrole při kompilaci a za běhu, a to po dobu trvání programu.Základní rozdíly mezi základní typy předdefinované a uživatelem definované typy jsou následující:
Kompilátor nemá žádný předdefinovaný typ definovaný uživatelem.Se "učí" typu při nalezne nejprve definice během kompilace.
Určete, jaké operace lze provádět na požadovaný typ a jak jej lze převést na jiné typy definováním (prostřednictvím přetížení) vhodných hospodářských subjektů, buď jako členů třídy, nebo třetí funkce.Další informace naleznete v tématu Přetěžování.
Není nutné být staticky zadané (pravidlo objektu zadejte nikdy změny).Prostřednictvím mechanismy dědičnost a polymorfismus, proměnná definovaná jako uživatelem definovaný typ třídy (označované jako instance objektu třídy) může mít jiného typu v době běhu než v době kompilace.Další informace naleznete v tématu Odvozené třídy.
Typy ukazatelů
Zakládalo nejstarší verze jazyka C, C++ nadále umožňují deklarovat proměnnou typu ukazatele pomocí speciální deklarátor * (hvězdička).Typ ukazatele ukládá adresu umístění v paměti, kde je uložena hodnota skutečná data.V moderních C++, ty jsou označovány jako raw ukazatelea jsou přístupné z kódu pomocí speciální operátory * (hvězdička) nebo -> (pomlčka s vyšší-než).Tento postup se nazývá Po zrušení referencí odkazuje, a který z nich použijete, závisí na po zrušení referencí zda jste se odkazuje ukazatel na skalární nebo ukazatele na člen v objektu.Práce s typy ukazatelů byl dlouhou dobu jedním z nejvíce náročné a matoucí aspektů rozvoje programu C a C++.Tato část popisuje některé skutečnosti a postupy pro zlepšení, použijte raw ukazatele, pokud chcete, ale v moderní C++ již má požadované (nebo doporučená) použití raw ukazatele pro vlastnictví objektu, vzhledem k vývoji inteligentní ukazatel (více naleznete na konci této části).Je stále užitečné a bezpečně používat raw ukazatele pro pozorování objektů, ale pokud je nutné použít pro vlastnictví objektu, měli byste tak učinit s opatrností a velmi pečlivě zvážit, jak jsou objekty, je vytvořen a zničeny.
První věcí, kterou byste měli vědět, je prohlašuje, že raw ukazatel Proměnná přidělí pouze paměť, která je povinna uložit adresu umístění v paměti, že ukazatel myši bude odkazující na, když je přímo odkázat.Přidělení paměti pro samotnou hodnotu dat (tzv. záložní úložiště) není dosud přidělen.Jinými slovy prohlášením raw ukazatel Proměnná vytvoříte proměnnou adresa paměti není proměnná skutečná data.Po zrušení referencí odkazuje proměnná ukazatel před Ujistěte se, zda neobsahuje platnou adresu k záložnímu úložišti způsobí nedefinované chování (obvykle závažné chyby) v programu.Následující příklad ukazuje tento druh chyby:
int* pNumber; // Declare a pointer-to-int variable.
*pNumber = 10; // error. Although this may compile, it is
// a serious error. We are dereferencing an
// uninitialized pointer variable with no
// allocated memory to point to.
V příkladu dereferences ukazatele typu bez nutnosti jakákoli paměť přidělená pro ukládání dat skutečné celé číslo nebo adresa platné paměti, které jí.Následující kód odstraňuje tyto chyby:
int number = 10; // Declare and initialize a local integer
// variable for data backing store.
int* pNumber = &number; // Declare and initialize a local integer
// pointer variable to a valid memory
// address to that backing store.
...
*pNumber = 41; // Dereference and store a new value in
// the memory pointed to by
// pNumber, the integer variable called
// “number”. Note “number” was changed, not
// “pNumber”.
Opravený kód příklad použití místního zásobníku paměti k vytvoření zálohování úložiště pNumber odkazuje.Používáme základní typ pro jednoduchost.V praxi, záložním úložištěm pro ukazatele jsou většina často uživatelem definované typy, které jsou dynamicky přiřazovány v oblasti paměti, nazývá haldy (nebo "zdarma") pomocí new výraz klíčové slovo (ve stylu C programování starší malloc() funkce knihovny runtime C byla použita).Po přidělení těchto "proměnné" jsou obvykle označovány jako "objekty", zejména v případě, že jsou založeny na definici třídy.Paměť přidělená s new musí být odstraněna odpovídající delete příkaz (nebo, pokud jste použili malloc() funkce přidělit ji funkce C runtime free()).
Je však snadno nezapomeňte odstranit dynamicky přiřazovány objekt-zejména komplexní kód, což způsobí, že zdroj chyby, nazývá nevracení paměti.Z tohoto důvodu není doporučeno v moderní C++ použití raw ukazatele.Je téměř vždy lepší obtékání raw ukazatel v inteligentní ukazatel, který bude automaticky uvolnit paměť, při jeho destruktor je vyvolána (v případě, že kód je mimo rozsah pro inteligentní ukazatele); pomocí inteligentní ukazatele prakticky eliminovat celou třídu chyby ve vašich aplikacích C++.V následujícím příkladu předpokládejme, MyClass je typ definovaný uživatelem, který má veřejná metodaDoSomeWork();
void someFunction() {
unique_ptr<MyClass> pMc(new MyClass);
pMc->DoSomeWork();
}
// No memory leak. Out-of-scope automatically calls the destructor
// for the unique_ptr, freeing the resource.
Další informace o chytré ukazatele, viz Inteligentní ukazatelů (Příručka programování moderních C++).
Další informace o převodech ukazatel, viz Převody typu a typ bezpečnosti (C++).
Další informace o ukazatele obecně naleznete v tématu Ukazatele.
Datové typy Windows
V klasické Win32 programování C a C++, většina funkcí pomocí funkce TypeDef specifické pro systém Windows a # definovat makra (podle windef.h) Chcete-li určit typy parametrů a vrácené hodnoty.Tyto "datové typy Windows" jsou z velké části pouze speciální názvy (aliasy) věnována předdefinované typy C/C++.Úplný seznam těchto funkce TypeDef a definiční soubory preprocesoru, viz Windows Data Types.Některé tyto funkce TypeDef, jako je například HRESULT a LCID, jsou užitečné a jsou popisné.Ostatní, jako je například INT, mají zvláštní význam a jsou pouze aliasy pro základní typy jazyka C++.Jiné typy dat systému Windows mají názvy, které jsou zachovány od dnů programování v C a 16bitové procesory a mít žádný účel nebo význam na moderní hardware nebo operační systémy.Existují také speciální datové typy, které jsou spojené s běhovou knihovnou Windows uveden jako Windows Runtime base data types.V moderních C++ je obecný návod tak, aby upřednostňovaly základních typů jazyka jazyka C++, pokud není typu Windows komunikuje některých dalších významů o jak má být interpretovány hodnotou.
Další informace
Další informace o systému typů jazyka C++ naleznete v následujících tématech.
Popisuje hodnotové typy spolu s problémy týkající se jejich použití. |
|
Popisuje běžné problémy při převodu typu a ukazuje, jak jim zabránit. |