A felügyelt típusok elérhetővé teszik a CLR szolgáltatásait, így élvezik annak előnyeit, de ugyanakkor bizonyos megszorítások is vonatkoznak rájuk. Minden felügyelt típus, illetve osztály egyetlen közös ősosztályból származik: az Object-ből.
A globális és lokális változók használatához a CLR támogatja az érték típusokat, amelyeket a __value kulcsszóval definiálunk. Az érték típusú objektumok mindig a veremben foglalnak helyet; nem lehet őket a new operátorral a dinamikus tárterületen elhelyezni. Ennek megfelelően az érték típusokból csak globális vagy lokális változót lehet létrehozni.
A beépített típusok, mint például az int, a short, a bool és a char, érték típusok, ezért esetükben a __value elhagyható.
A beépített típusok:
Típus | Csomagoló osztály | Min. érték | Max. érték | Leírás |
short | System::Int16 | -32768 | 32767 | 16 bites előjeles egész |
int | System::Int32 | -2 147 483 648 | 2 147 483 647 | 32 bites előjeles egész |
long | System::Int64 | -9 223 372 036 854 775 808 | 9 223 372 036,854 775 807 | 64 bites előjeles egész |
unsigned short | System::UInt16 | 0 | 65535 | 16 bites előjel nélküli egész |
unsigned int | System::UInt32 | 0 | 4 294 967 295 | 32 bites előjel nélküli egész |
unsigned long | System::UInt64 | 0 | 18 446 744 073 709 551 615 | 64 bites előjel nélküli egész |
bool | System::Boolean | false | true | Logikai típus |
__wchar_t | System::Char | 0x0000 | 0xFFFF | Unicode karakter |
unsigned char | System::Byte | -128 | 127 | Előjeles bájt |
char | System::SByte | 0 | 255 | Előjel nélküli bájt |
float | System::Single | -3.402823e38 | 3.402823e38 | Előjeles 32 bites lebegőpontos valós |
double | System::Double | -1.79769313486232e308 | 1.79769313486232e308 | Előjeles 64 bites lebegőpontos valós |
A fenti típusok az alábbi interfészeket implementálják: IComparable (összehasonlítható), IFormattable (formázható), és IConvertible (konvertálható). Mindegy, hogy deklaráláskor a hagyományos C++-beli típuselnevezést használjuk vagy az elfedő osztály nevét. Az elfedő osztályok különböző hasznos metódusokat tartalmaznak, úgy, mint:
Struktúrák. Ezt a típust a C++-ban megszokottak szerint használjuk, annyi különbséggel, hogy a egy plusz __value kulcsszó kerül a struct elé:
Az érték típusokat csak a felügyelt tárterületen nem lehet dinamikusan létrehozni. Az _nogc kulcsszóval az érték típú változók elhelyezhetők a felügyeletlen dinamikus tárterületen.
A módszer hátulütője, hogy a virtuális gép elveszti a szemétgyűjtés lehetőségét, mivel a felügyeletlen területet definíció szerint nem tudja felügyelni. Ezért a fenti kód esetén fennáll a memórielszivárgás veszélye. A megoldás olyan esetekben szükséges, amikor a programban felügyeletlen entitásokat kell használni. A new operátor __nogc-os verziója természetesen nem használható nem érték típusoknál.
Tömbök. Minden felügyelt tömb a System::Array osztályból származik. Tömbök deklarációja érték típusok esetén eltér a C++-tól. Általában: Típus Azon __gc[méret]. A __gc kucsszót elhagyva felügyeletlen tömböt kapunk. Felügyelt referencia típus esetén nem kötelező a kulcsszó használata.
Példa egy egészeket tartalmazó egydimenziós tömbre:
Többdimenziós tömb esetén is más a szintaktika. Általában: Típus Azon __gc[,,..,], ahol a vesszők száma a dimenziót adja meg.
Az indexelés sem egyezik a megszokottal a többdimenziós esetben:
Gyakran van szükség arra, hogy a CLR dinamikus tárterületén hozzunk létre egy érték típusú változót. Ez megtehető például úgy, ha az érték típust becsomagoljuk egy referencia típusú osztályba, és annak az objektumait helyezzük el felügyelt memóriában. Mivel gyakran szükség lehet erre, a nyelv egy programozóbarátabb megoldást is kínál a probléma megoldására, melynek neve dobozolás (boxing).
A dobozolás elkészíti egy érték típusú objektum felügyelt másolatát és a CLR heapjébe helyezi. Ehhez a __box kulcsszót kell használni, amely bitenként átmásolja az objektumot a felügyelt objektumba, ami System::ValueType típusú (azaz leszármazottja a System::Object-nek). Az új felügyelt objektum címét adja vissza. Fontos: a létrehozott másolaton a változtatások nem hatnak vissza az eredeti érték típusú objektumra.
Példa:
A dobozolás viszonylag drága mulatság, és amíg C#-ban implicit módon történik, Managed C++-ban explicite jelezni kell ezt a szándékunkat. (Teljesítménybeli megfontolások miatt van így.)
Egy érték típusú osztály dobozolt példányát a __dynamic_cast, vagy a __try_cast kulcsszavak használatával kaphatjuk meg. Ezek egy mutatóval térnek vissza, amelyet dereferálva visszakapjuk az érték típusú objektumot. Az eljárást kidobozolásnak hívják.
Példa:
A felügyelt osztályok főbb tulajdonságai:
Főbb jellegzetességek | Főbb megszorítások |
|
|
Zárolt (__sealed) osztályok. A zárolt osztályokból nem lehet más osztályokat származtatni. Taggfüggvényeket is elláthatunk ezzel a kulcsszóval: a zárolt tagfüggvényeket nem lehet felüldefiniálni az osztály leszármazottaiban. A kulcsszó csak felügyelt osztályokra alkalmazható, felügyeletlen osztályokra és interfészekre nem. (Természetesen, hiszen mi értelme volna egy olyan interfésznek, amiből nem lehet származtatni?)
Absztrakt (__abstract) osztályok. Az absztrakt osztályok a tervezés eszközei. Nem lehet példányosítani őket, csak leszármazottaikat. Ennek értelmében tehát zárolt osztályokra nem alkalmazható (mivel azokból nem lehet származtatni).
Felügyelt interfészek. Olyanok mint az osztályok, csak minden tagfüggvényük absztrakt, és nem tartalmazhatnak implementációt. Az __interface kulcsszóval vezethetjük be őket. Lehet bennük érték felsorolási típus (__value enum). Az interfészekben nem kell explicite jelölni, hogy egy tagfüggvény virtuális (a virtual kulcsszóval) és absztrakt (az = 0 szuffixummal), mivel nem is lehet más.
Főbb megszorításai: