Ve skutečnosti dva nezávislé typové systémy ◦ native original ISO C++ ◦ managed fuj - manažovaný - řízený CTS ◦ string vs. String, vector vs. array
Garbage collection
◦ pouze CTS ◦ managed heap ◦ handle není to ukazatel může se měnit ◦ nové operátory: gcnew ^ % ◦ reference vs. value type
native heap class Native {...}; ref class Managed {...}; { Native* n = new N; Managed^ m = gcnew Managed; delete n; }
handle
managed heap
Typy
hodnotové
referenční
data
primitivní typy, malé kolekce
složitější struktury
umístění
přímo v paměti (zásobník)
vždy na [managed] heapu
přístup
přímo
přes [tracking] handle
přiřazení, parametry
hodnotou
odkazem
dědičnost
ne
jednoduchá (více interfaces)
copy constr
ano
ne
default sémantika
stack heap s.: boxing
heap stack s.: autoalokace
value struct B { int x; }; int main() { B b; b.x = 0; }
ref class A { int f(); }; int main() { A^ a = gcnew A; a->f(); }
ref class, ref struct
◦ nesmí obsahovat nemanaged struktury ◦ nemají automatický copy constructor a operator = ◦ jednoduchá dědičnost, vícenásobná dědičnost interface
value class, value struct
◦ nepodporují dědičnost !
enum class
◦ rozšíření enumu o několik metod - ToString ◦ value type
interface class
◦ abstract class bez dat ◦ možnost vícenásobné dědičnosti
array
◦ typované vícerozměrné pole
generic
Referenční typy
◦ proměnné ≈ reference na data ◦ neinicilizované: nullptr přístup přes nullptr ⇒ NullReferenceException ◦ přiřazení ≈ kopírování referencí, nikoliv dat není automaticky definován copy konstruktor ◦ konec existence poslední reference ⇒ někdy garbage collection ◦ možná i zásobníková sémantika technicky ale stále heap, na konci platnosti destruktor ref class A { int f(); };
ra va
... { A^ ra = gcnew A; A va; ra->f(); va.f(); }
destruktor va
ra
ra
va
někdy možná GC a finalizer
Hodnotové typy ◦ ◦ ◦ ◦
proměnné ≈ vlastní data přiřazení ≈ kopírování dat nelze dědičnost boxing - alokace na heapu
value struct B { int x; }; fnc( B^ b) { b->x = 2; }
tracking reference ◦ T% y = *x; ◦ T% y = var; ◦ y.a
◦ unmanaged: & přímo nelze jen na objekty na zásobníku
value class T; T a; T^ b = gcnew T; T^ c = %a; T% d = a; T% e = *b; T* f = &a; // T* g = b; pin_ptr g = &*b; // T* h = &d; pin_ptr h = &d; T& i = a; // T& j = *b;
technicky: ukazatel dovnitř managed objektu
a b c
b a
d e f g h i
kopie do managed heapu !!
ISO C++
◦ volá se metoda aktuálně konstruovaného podobjektu
C++/CLI
◦ volá se metoda skutečného (vnějšího) objektu
class A { A() : x(0) { x = f(); } virtual int f() { return x + 1; } int x; }; class B : public A { public: B() { x = f(); } virtual int f() { return };
x + 2; }
A* b = new B;
ref class C { public: C() : x(0) { x = f(); } virtual int f() { return int x; };
x + 1; }
ref class D : C { public: D() { x = f(); } virtual int f() override { return x + 2; } }; C^ d = gcnew D;
A() { A::f() }, B() { B::f() } x=3
C() { D::f() }, D() { D::f() } x=4
rozhraní interface class IA { int f(); }; ref class A abstract : IA { public: A8() { x_ = 1; } virtual int f() abstract; ~A8() { cout << "~"; } !A8() { cout << "!"; } private: initonly int x_; };
vícenásobná dědičnost rozhraní destruktor deterministicky finalizer - při GC nedeterministicky přiřazení pouze při inicializaci jen jednoduchá dědičnost tříd
ref class B8 sealed : A8 { public: virtual int f() override sealed {...} };
nepodporovány - default parametry - const metody
ref class C { const int f(int x=1,int y=2); };
ref class A { public: property int a; property int b { int get() { return x_; } void set( int x) { x_ = x; } } property int c[int] { int get( int i) { return (x_>>i)&1; } void set( int i, int x) { x_ ^= (x&1)<a = a->b; a->c[1] = a[2];
trivial property standard property indexed property default indexed property
dědičnost
◦ virtual property
read/write-only
◦ lze nadefinovat jen get/set
static property
◦ přístup jen k statickým prvkům
Delegate
◦ ukazatel na funkci nebo metodu konkrétního objektu
pole built-in povinně referenční typ, vždy na heapu typované, pevně vícerozměrné, 0-based vícerozměrné indexy [i,j,k] iterace možná i přes iteratory, interior ptr a for each přiřazení ≈ reference, Array::Copy kopie array< String^>^ as array< int, 2>^ a2d array< int, 2>^ a2d array< int, 2>^ a2d array< int, 2>^ a2d int x = a2d[1,2];