Sdílet prostřednictvím


Přehled obecných typů v C++/CLI

Obecné typy jsou parametrizované typy podporované modulem CLR (Common Language Runtime). Parametrizovaný typ je typ definovaný pomocí neznámého parametru typu, který je zadán při použití obecného typu.

Proč generické typy?

Jazyk C++ podporuje šablony a šablony i obecné typy podporují parametrizované typy pro vytváření tříd typových kolekcí. Šablony však poskytují parametrizaci v době kompilace. Nelze odkazovat na sestavení obsahující definici šablony a vytvořit nové specializace šablony. Po kompilaci vypadá specializovaná šablona jako jakákoli jiná třída nebo metoda. Naproti tomu obecné typy jsou generovány v prostředí MSIL jako parametrizovaný typ známý modulem runtime jako parametrizovaný typ; zdrojový kód, který odkazuje na sestavení obsahující obecný typ, může vytvořit specializace obecného typu. Další informace o porovnání standardních šablon jazyka C++ a obecných typů najdete v tématu Obecné typy a šablony (C++/CLI).

Obecné funkce a typy

Typy tříd, pokud jsou spravované typy, mohou být obecné. Příkladem může být List třída. Typ objektu v seznamu by byl parametr typu. Pokud potřebujete List třídu pro mnoho různých typů objektů, před obecnými typy jste mohli použít typ List System::Object položky. To by ale umožnilo použití libovolného objektu (včetně objektů nesprávného typu) v seznamu. Takový seznam by se nazývá netypová třída kolekce. V nejlepším případě můžete zkontrolovat typ za běhu a vyvolat výjimku. Nebo jste mohli použít šablonu, která by po kompilaci do sestavení ztratila její obecnou kvalitu. Příjemci sestavení nemohli vytvořit vlastní specializace šablony. Obecné typy umožňují vytvořit typové třídy kolekce, například List<int> (číst jako "Seznam int") a List<double> ("Seznam dvojitých") a který by vygeneroval chybu v době kompilace, pokud jste se pokusili vložit typ, který kolekce nebyla navržena tak, aby přijímala do typované kolekce. Kromě toho tyto typy zůstávají po kompilaci obecné.

Popis syntaxe obecných tříd lze najít v obecných třídách (C++/CLI). Nový obor názvů , System.Collections.Genericzavádí sadu parametrizovaných typů kolekce včetně Dictionary<TKey,TValue>a List<T> LinkedList<T>.

Členské funkce instance i statické třídy, delegáty a globální funkce mohou být také obecné. Obecné funkce mohou být nezbytné, pokud jsou parametry funkce neznámého typu nebo pokud samotná funkce musí pracovat s obecnými typy. V mnoha případech, kdy System::Object bylo možné použít v minulosti jako parametr neznámého typu objektu, lze místo toho použít parametr obecného typu, což umožňuje více typově bezpečný kód. Jakýkoli pokus o předání typu, pro který nebyla funkce navržena, by byl označen jako chyba v době kompilace. Při použití System::Object jako parametru funkce by nechtěné předávání objektu, se kterým funkce nebyla určena, nebyla zjištěna a vy byste museli přetypovat neznámý typ objektu na konkrétní typ v těle funkce a zohlednit možnost InvalidCastException. V případě obecného kódu, který se pokouší předat objekt funkci, by způsobil konflikt typu, takže tělo funkce je zaručeno, že správný typ.

Stejné výhody platí pro třídy kolekcí založené na obecných objektech. Třídy kolekcí v minulosti by se použily System::Object k ukládání prvků v kolekci. Vložení objektů typu, pro který nebyla kolekce navržena, nebyla v době kompilace označena příznakem, a často ani v případě, že byly vloženy objekty. Objekt by se obvykle přetypoval na jiný typ, když byl v kolekci přístupný. Pouze v případech, kdy se přetypování nezdařilo, byl zjištěn neočekávaný typ. Obecné typy tento problém řeší v době kompilace tím, že zjistí jakýkoli kód, který vloží typ, který neodpovídá (nebo implicitně převede na) parametr typu obecné kolekce.

Popis syntaxe najdete v tématu Obecné funkce (C++/CLI).

Terminologie používaná s obecnými typy

Parametry typu

Obecná deklarace obsahuje jeden nebo více neznámých typů, které se označují jako parametry typu. Parametry typu mají název, který je zkratkou pro typ v těle obecné deklarace. Parametr type se používá jako typ v těle obecné deklarace. Obecná deklarace obsahuje List<T> parametr typu T.

Argumenty typu

Argument typu je skutečný typ použitý místo parametru typu, pokud je obecný specializovaný pro určitý typ nebo typy. Jedná se například int o argument typu v List<int>. Typy hodnot a popisovače jsou jedinými typy, které jsou povoleny jako argument obecného typu.

Vytvořený typ

Typ vytvořený z obecného typu se označuje jako konstruovaný typ. Typ, který není plně zadán, například List<T> otevřený konstruovaný typ; typ plně zadaný, například List<double>, je uzavřený konstruovaný typ nebo specializovaný typ. Otevřené konstruované typy lze použít v definici jiných obecných typů nebo metod a nemusí být plně zadány, dokud není zadán samotný uzavřený obecný. Například toto je použití otevřeného vytvořeného typu jako základní třídy pro obecný typ:

// generics_overview.cpp
// compile with: /clr /c
generic <typename T>

ref class List {};

generic <typename T>

ref class Queue : public List<T> {};

Omezení

Omezení je omezení pro typy, které lze použít jako parametr typu. Například daná obecná třída může přijímat pouze třídy, které dědí ze zadané třídy, nebo implementovat zadané rozhraní. Další informace naleznete v tématu Omezení obecných parametrů typu (C++/CLI).

Referenční typy a typy hodnot

Popisovače typů a hodnotových typů lze použít jako argumenty typu. V obecné definici, ve které lze použít některý typ, syntaxe je odkazové typy. Operátor se například -> používá pro přístup ke členům typu parametru typu, zda je typ nakonec použit jako referenční typ nebo typ hodnoty. Pokud se jako argument typu použije typ hodnoty, modul runtime vygeneruje kód, který používá typy hodnot přímo bez pole typů hodnot.

Při použití typu odkazu jako argumentu obecného typu použijte syntaxi popisovače. Při použití typu hodnoty jako argumentu obecného typu použijte přímo název typu.

// generics_overview_2.cpp
// compile with: /clr
generic <typename T>

ref class GenericType {};
ref class ReferenceType {};

value struct ValueType {};

int main() {
    GenericType<ReferenceType^> x;
    GenericType<ValueType> y;
}

Parametry typu

Parametry typu v obecné třídě jsou považovány za jiné identifikátory. Vzhledem k tomu, že typ není známý, existují omezení jejich použití. Například nelze použít členy a metody třídy parametru typu, pokud parametr typu není známý pro podporu těchto členů. To znamená, že pokud chcete získat přístup k členu prostřednictvím parametru typu, musíte přidat typ, který obsahuje člena do seznamu omezení parametru typu.

// generics_overview_3.cpp
// compile with: /clr
interface class I {
   void f1();
   void f2();
};

ref struct R : public I {
   virtual void f1() {}
   virtual void f2() {}
   virtual void f3() {}
};

generic <typename T>
where T : I
void f(T t) {
   t->f1();
   t->f2();
   safe_cast<R^>(t)->f3();
}

int main() {
   f(gcnew R());
}

Tato omezení platí i pro operátory. Parametr obecného typu bez omezení nemusí používat == operátory a != porovnat dvě instance parametru typu v případě, že typ tyto operátory nepodporuje. Tyto kontroly jsou nezbytné pro obecné typy, ale ne pro šablony, protože obecné typy mohou být specializované za běhu s libovolnou třídou, která splňuje omezení, pokud je příliš pozdě zkontrolovat použití neplatných členů.

Pomocí operátoru lze vytvořit výchozí instanci parametru () typu. Příklad:

T t = T();

kde T je parametr typu v obecné třídě nebo definici metody, inicializuje proměnnou na výchozí hodnotu. Pokud T je referenční třída, bude to nulový ukazatel; pokud T je třída hodnoty, objekt je inicializován na nulu. Tomu se říká výchozí inicializátor.

Viz také

Obecné typy