Visual C++/CLI. Języki Programowania na Platformie.NET (część 2) Tomasz Goluch. http://www.kaims.pl/ goluch/ goluch@eti.pg.gda.pl



Podobne dokumenty
PARADYGMATY PROGRAMOWANIA Wykład 4

Instrukcja laboratoryjna cz.3

Kurs programowania. Wykład 13. Wojciech Macyna. 14 czerwiec 2017

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Szablony klas, zastosowanie szablonów w programach

Wykład 5 Okna MDI i SDI, dziedziczenie

Wykład 8: klasy cz. 4

Zaawansowane programowanie w C++ (PCP)

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Materiały do zajęć VII

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Programowanie 2. Język C++. Wykład 3.

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Szablony. Szablony funkcji

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Zaawansowane programowanie w języku C++ Klasy w C++

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Wprowadzenie w dziedziczenie. Klasa D dziedziczy klasę B: Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class).

Funkcje wirtualne. Wskaźniki do klas pochodnych są podstawą dla funkcji wirtualnych i polimorfizmu dynamicznego.

Wykład 4: Klasy i Metody

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

.NET Klasy, obiekty. ciąg dalszy

Wstęp do Programowania 2

Język C++ Programowanie obiektowe

Programowanie w języku C++

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

C# 6.0 : kompletny przewodnik dla praktyków / Mark Michaelis, Eric Lippert. Gliwice, cop Spis treści

Programowanie obiektowe w C++ Wykład 12

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Programowanie obiektowe

EGZAMIN PROGRAMOWANIE II (10 czerwca 2010) pytania i odpowiedzi

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Szablony funkcji i szablony klas

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Abstrakcyjny typ danych

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

ZASADY PROGRAMOWANIA KOMPUTERÓW

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Kurs WWW. Paweł Rajba.

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Wykład V. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Dziedziczenie jednobazowe, poliformizm

Programowanie w środowiskach graficznych. Wykład 3 Język C#

Dziedziczenie. dr Jarosław Skaruz

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy KONSTRUKTORY

Języki i metodyka programowania. Język C# pętle, sterowanie, wyjątki

Wprowadzenie do szablonów szablony funkcji

Obsługa wyjątków. Język C++ WW12

Programowanie obiektowe

Wprowadzenie do szablonów szablony funkcji

Rozdział 4 KLASY, OBIEKTY, METODY

TEMAT : KLASY DZIEDZICZENIE

Wykład 3 Składnia języka C# (cz. 2)

Klasy cd. Struktury Interfejsy Wyjątki

Co to jest klasa? Z programistycznego punktu widzenia klasa stanowi typ danych, który odwzorowuje wspólne cechy jakiegoś obiektu.

Programowanie Komputerów

Programowanie obiektowe w języku C++ dr inż. Jarosław Forenc

Szablony funkcji i klas (templates)

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Zaawansowane programowanie w C++ (PCP)

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

Operator przypisania. Jest czym innym niż konstruktor kopiujący!

Dziedziczenie. Tomasz Borzyszkowski

Język C++ wykład VII. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VII. dr Jarosław Mederski. Spis.

PARADYGMATY PROGRAMOWANIA Wykład 2

Programowanie obiektowe

Wstęp do programowania

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

Jeśli chcesz łatwo i szybko opanować podstawy C++, sięgnij po tę książkę.

Programowanie obiektowe

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Klasy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 13

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

Języki i techniki programowania Ćwiczenia 3 Dziedziczenie

Lab 9 Podstawy Programowania

Projektowanie obiektowe. Roman Simiński Polimorfizm

Multimedia JAVA. Historia

Zaawansowane programowanie w C++ (PCP)

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Microsoft IT Academy kurs programowania

Programowanie 2. Język C++. Wykład 9.

Dziedziczenie. Ogólna postać dziedziczenia klas:

Definicje klas i obiektów. Tomasz Borzyszkowski

Zaawansowane programowanie w C++ (PCP)

EGZAMIN 2 (14 WRZEŚNIA 2015) JĘZYK C++

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

1. Klasa typu sealed. Przykład 1. sealed class Standard{ class NowyStandard:Standard{ // błd!!!

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

Transkrypt:

Języki Programowania na Platformie.NET (część 2) http://www.kaims.pl/ goluch/ goluch@eti.pg.gda.pl

Zalety i wady pozwala na uaktualnianie aplikacji i komponentów o właściwości platformy.net bez konieczności przepisywania kodu pozwala na wykorzystywanie natywnych i zarządzanych bibliotek w jednym projekcie, pliku źródłowym, klasie a nawet metodzie. pozwala pisać programy, które wymagają efektywnego przetwarzania danych binarnych oraz posiadają złożony interfejs graficzny (Windows Forms, WPF) wymaga zainstalowanej w systemie odpowiedniej wersji frameworka.net w praktyce nie współpracuje z Linuxem i innymi systemami operacyjnymi

Rodzaje kodu mieszany (mixed), /clr: moduł zawiera zarówno kod zarządzany jak i niezarządzany czysty (pure), /clr:pure: posiada zarówno natywne i zarządzane typy danych, lecz wyłącznie zarządzane funkcje bezpieczny (safe), /clr:safe: tylko zarządzany kod

Zalety /clr:pure większa wydajność (brak funkcji niezarządzanych nie potrzebne są przejścia z trybu zarządzanego w niezarządzany) kod istnieje wewnątrz AppDomain brak konieczności umieszczania modułów na dysku w celu kompilacji i uruchomienia pełne wsparcie dla reflection Jedna z wad: brak możliwości wywoływania takiego kodu przez kod niezarządzany. Pozwala jednak na współpracę z natywnymi bibliotekami przy pomocy mechanizmu PInvoke

Zalety /clr:safe większe bezpieczeństwo w niektórych sytuacjach wymagane (np. przez komponenty SQL) nieuchronnie rosnąca popularność w przyszłości Kompilacja kodu korzystającego z wywołań natywnych bibliotek za pomocą PInvoke zawsze się powiedzie, jednak w zależności od ustawień zabezpieczeń może powodować błędy wykonania.

PInvoke (Platform Invocation Service) PInvoke to zbior usług CLR odpowiedzialnych za: odnalezienie biblioteki z żądaną funkcją załadowanie biblioteki do pamięci odnalezienie adresu f-cji i jej wywołanie wraz z przekazaniem parametrów zbiór klas związanych z PInvoke zawarty jest w przestrzeni nazw System.Runtime.InteropServices

PInvoke (Platform Invocation Service) // PInvokeTest.cs using System; using System.Runtime.InteropServices; class PlatformInvokeTest { [DllImport("msvcrt.dll")] public static extern int puts(string c); [DllImport("msvcrt.dll")] internal static extern int _flushall(); public static void Main() { puts("test"); _flushall();

Definicja klasy zarządzanej przykład ref class A { public: void f() { ; A ^a; a->f(); a = nullptr;

Definicja klasy class_access ref class name modifier : inherit_access base_type {; class_access ref struct name modifier : inherit_access base_type {; class_access value class name modifier : inherit_access base_type {; class_access value struct name modifier : inherit_access base_type {; ref informuje kompilator, że klasa lub struktura będzie umieszczona na stercie i referencja do niej będzie używana jako parametr funkcji lub składowa w klasach, value informuje kompilator, że zawartość klasy będzie przekazywana do funkcji/przechowywana w zmiennych.

Definicja klasy c.d. class_access, tylko: public lub private inherit_access: public modifier to abstract lub sealed składowe klasy sa domyślnie prywatne, natomiast składowe struktur są domyślnie publiczne typ value nie może być typem bazowym fuckcje wirtualne w typach referencyjnych muszą być deklarowane w klasach pochodnych z użyciem słowa kluczowego override lub new (przeciążenie albo przysłonienie metody klasy bazowej) do dynamicznego tworzenia klas używamy gcnew

Zmienne na stosie a GC gdy deklarujemy zmienną na stosie (stacs semantics), kompilator wygeneruje kod tworzący obiekt na stercie za pomocą gcnew deklaracja argumentu do funkcji lub zwracanej wartości z użyciem stacs semantics sprawia, że funkcja nie może być używana przez inne języki kompilator nie generuje konstruktorów kopiujących dla typów referencyjnych, należy więc zdefiniować samodzielnie (C(C%){) kompilator również nie generuje domyślnego operatora przypisania, więc możliwość tworzenia obiektów z użyciem stacs semantics wymaga jego definicji (void operator=(c%){)

Zmienne na stosie a GC cd kompilator dostarcza jednoargumentowego operatora % konwertującego zmienną zadeklarowaną z użyciem stacs semantics do odpowiadającego typu referencyjnego nie można powyższej notacji używać w przypadku typów delegate, array, String

Zmienne na stosie a GC przykład ref class R { public: int i; R(){ void operator=(r% r) { // operator przypisania i = r.i; ; R(R% r) : i(r.i) { // konstuktor kopiujący void Test(R r) { // wymaga konstruktora kopiującego W przypadku typu value powyższe operatory i konstruktory są niedozwolone

Zmienne na stosie a GC przykład cd R r1; r1.i = 98; R r2(r1); // wymaga konstruktora kopiującego System::Console::WriteLine(r1.i); // 98 System::Console::WriteLine(r2.i); // 98 R ^ r3 = %r1; // % konwertuje obiekt ze stosu do typu // referencyjnego System::Console::WriteLine(r3->i); // 98 Test(r1); R r4, r5; r5.i = 13; r4 = r5; // wymaga zdefiniowania operatora przypisania System::Console::WriteLine(r4.i); // 13 R % r6 = r4;// tracking reference (nigdy null oraz nullptr) System::Console::WriteLine(r6.i); // 13 http://msdn.microsoft.com/en-us/library/ms177191.aspx

Destruktory class A { ~A() { // destruktor!a() { // finalizer ; druga z metod jest destruktorem wywoływanym przy pracy GC niebezpieczne jest odwoływanie się do zarządzanych danych w metodzie!a (mogły już zostać zwolnione, ponieważ garbage collector zwalnia zarządzane zasoby niedeterministycznie), metoda!a nie jest równoważna metodzie Finalize (automatyczne wywoływanie w całej hierarchii; dokumentacja clr) GC wywołuje Finalize, która wywołuje wiele destruktorów poprzedzonych!, znajdujących się w hierarchii dziedziczenia destruktor wywołując!a nie powoduje ciągu wywołań w klasach bazowych

Typowy schemat destruktor-finalizer ref class A { // destruktor (zwalnia wszystkie zasoby) ~A() { // zwolnij zarządzane zasoby // następnie wywołaj finalizer: this->!a(); ; // finalizer (zwalnia niezarządzane zasoby)!a() { // zwolnij niezarządzane zasoby

Kiedy wywoływany jest destruktor? jeśli obiekt został utworzony za pomocą stacs semantics i sterowanie opuściło dany zakres, gdy pojawi się wyjątek podczas tworzenia obiektu, jeśli obiekt jest składową, której destruktor został uruchomiony, gdy zostanie użyty operator delete na referencji do obiektu, gdy jawnie wywołamy destruktor.

Referencja % ref struct A { void Test(unsigned int &){ void Test2(unsigned int %){ unsigned int i; ; int main() { A a; a.i = 9; a.test(a.i); // C2664 a.test2(a.i); // OK unsigned int j = 0; a.test(j); // OK http://msdn.microsoft.com/en-us/library/yk97tc08.aspx

Referencja % ref class MyClass { public: int i; int k; ; value struct MyStruct { ; int main() { MyClass ^ x = gcnew MyClass; MyClass ^% y = x; // adres referencji do obiektu int %ti = x->i; // element obiektu int j = 0; int %tj = j; // obiekt na stosie int * pi = new int[2]; int % ti2 = pi[0]; // obiekt na stercie \Cpp int *% tpi = pi; // wskaźnik \Cpp MyStruct ^ x2 = gcnew MyStruct; MyStruct ^% y2 = x2; http://msdn.microsoft.com/en-us/library/8903062a

Referencja % przypomina standardową referencję C++, referencja % może być deklarowana wyłącznie na stosie, wskazuje na obiekty lub składowe,

Uchwyt wskaźniki * i referencje & nie mogą być użyte w kontekście sterty zarządzanej przez GC używamy ^ w celu przechowywania uchwytów/referencji do całych obiektów; GC może przesuwać takie obiekty ref class MyClass { public: MyClass() { void Test() { System::Console::WriteLine("hello"); ; int main() { MyClass ^ p1 = gcnew MyClass; p1->test(); MyClass ^ p2; p2 = p1; p1 = nullptr; p2->test();

Odwołania do zarządzanych typów z niezarządzanego kodu #include <vcclr.h> using namespace System; class CppClass { public: gcroot<string^> str; ; CppClass() { // can use str as // if it were String^ int main() { CppClass c; c.str = gcnew String("hello"); Console::WriteLine( c.str ); http://msdn.microsoft.com/en-us/library/481fa11f.aspx // no cast required

Słowa kluczowe abstract i sealed funkcja abstakcyjna = pusta funkcja wirtualna słowo kluczowe abstract również może być używane przy kompilacji standardowej ref class X abstract { public: virtual void f() {; virtual void g() abstract; ; sealed w odniesieniu do klasy: nie może być klasą bazową dla żadnej innej; w odniesieniu do funkcji: nie może być przesłaniana w klasie bazowej, błąd C3246 (przykład 2): http://msdn.microsoft.com/en-us/library/0w2w91tf.aspx

przestrzeń nazw cli można dołączyć poprzez using namespace cli; (automatycznie włączona podczas kompilacji /clr) definiuje słowa kluczowe: array pin_ptr interior_ptr safe_cast

Dynamiczne tablice [qualifiers] [cli::]array<[qualifiers]type1[, dimension]>^var = gcnew name [cli::]array<type2[, dimension]>(val[,val...]) dimension liczba wymiarów tablicy, domyślnie 1, maksymalnie 32 val liczba elementów tablicy (dla każdego wymiaru) type1 typ elementów tablicy type2 typ elementów inicjalizujących tablicę (zwykle = type1, a w przeciwnym wypadku musi być możliwa konwersja) name nazwa zmiennej tablice są zarządzanymi obiektami brak arytmetyki na indeksach

Jednowymiarowa tablica ref class A { public: int i; ; array<a^>^ f() { int i; array<a^>^ ar = gcnew array<a^>(5); for (i = 0; i < 5; i++) { ar[i] = gcnew A; ar[i]->i = i; return ar;

Tablica wielowymiarowa array<int32, 2>^ Test1() { int i, j; array< Int32,2 >^ local = gcnew array< Int32,2 >( ARRAY_SIZE, ARRAY_SIZE); for (i = 0 ; i < ARRAY_SIZE ; i++) for (j = 0 ; j < ARRAY_SIZE ; j++) local[i,j] = i + 10; return local; http://msdn.microsoft.com/en-us/library/2xfh4c7d.aspx

typedef dla zarządzanej tablicy using namespace System; ref class G {; typedef array<array<g^>^> some_array; int main() { some_array ^ MyArr = gcnew some_array (10); Tablice tablic (przykład 3): http://msdn.microsoft.com/en-us/library/fkzha470.aspx

Zarządzane tablice jako parametry szablonu using namespace System; template <class T> class TA { public: array<array<t>^>^ f() { array<array<t>^>^ larr = gcnew array<array<t>^>(10); return larr; ; int main() { int retval = 0; TA<array<array<Int32>^>^>* ta1 = new TA<array<array<Int32>^>^>(); array<array<array<array<int32>^>^>^>^ larr = ta1->f(); retval += larr->length - 10; Console::WriteLine("Return Code: {0", retval); http://msdn.microsoft.com/en-us/library/8cc87xcw.aspx

Sortowanie zarządzanej tablicy zarządzane tablice dziedziczą zachowanie od klasy bazowej przykład to sortowanie tablicy: Array::Sort(tab); elementy tablicy muszą implementować metodę IComparable::CompareTo

Sortowanie zarządzanej tablicy przykład value struct Element : public IComparable { int v1, v2; int CompareTo(Object^ obj) { Element^ o = dynamic_cast<element^>(obj); if (o) { int thisaverage = (v1 + v2) / 2; int thataverage = (o->v1 + o->v2) / 2; if (thisaverage < thataverage) return -1; else if (thisaverage > thataverage) return 1; return 0; else throw new ArgumentException("o must be of type Element "); ; int main() { array<element>^ a = gcnew array<element>(10);... Array::Sort( a ); http://msdn.microsoft.com/en-us/library/s9xfdtye.aspx

interior ptr [cli::]interior_ptr<cv_qualifier type> var = &initializer; Przykład: using namespace System; ref class MyClass { public: int data; ; int main() { MyClass ^ h_myclass = gcnew MyClass; h_myclass->data = 1; Console::WriteLine(h_MyClass->data); interior_ptr<int> p = &(h_myclass->data); *p = 2; Console::WriteLine(h_MyClass->data); // alternatywnie: interior_ptr<myclass ^> p2 = &h_myclass; (*p2)->data = 3; Console::WriteLine((*p2)->data); http://msdn.microsoft.com/en-us/library/y0fh545k.aspx

pin ptr [cli::]pin_ptr<cv_qualifier type> var = &initializer; używanie podobne do interior_ptr, lecz uniemożliwia GC przesuwanie wskazywanego obiektu, używamy, gdy chcemy przekazać adres zarządzanego zasobu do niezarządzanego kodu mamy gwarancje, ze adres zarządzanego obiektu znajdującego się na (zarządzanej) stercie nie ulegnie zmianie związanie elementu obiektu ma efekt związania całego obiektu jeśli wartość wskaźnika ulegnie zmianie, to możliwe jest przesuwanie poprzedniego obiektu przez GC jeśli sterowanie zostanie przekazane poza blok z deklaracją takiego wskaźnika, to również GC może przesuwać dane

delegate [dostęp] delegate deklaracja_funkcji public delegate void ExDel(int i); ref class A { public: void f(int i) {... void g(int i) {... ; int main() { A^ a = gcnew A; ExDel^ d; if (d) d(7); d = gcnew ExDel(a, &A::f); d(8); DelInst += gcnew ExDel(a, &A::g);

Szablony a typy generyczne szablony są statyczne, tzn. konkretne instancje typów tworzone są podczas kompilacji kodu, instancje dla szablonów tworzone są w trakcie wykonania kodu w konsekwencji nie można tworzyć konkretnych instancji szablonów (specjalizacji) mając dostęp do skompilowanego modułu, a takiego ograniczenia nie ma w przypadku typów generycznych

Typy generyczne przykład using namespace System; generic <typename ItemType> ref struct Stack { // ItemType may be used as a type here void Add(ItemType item) { ; generic <typename KeyType, typename ValueType> ref class HashTable {; // The keyword class may be used instead of typename: generic <class ListItem> ref class List {; int main() { HashTable<int, Decimal>^ g1=gcnew HashTable<int, Decimal>(); http://msdn.microsoft.com/en-us/library/skef48fy.aspx

Opakowania kodu ANSI C++ Sposobem na użycie niezarządzanego kodu C++z poziomu VB lub C#jest napisanie zarządzanego opakowania dla niezarządzanej klasy. Jeśli klasa niezarządzana nosi nazwę UClass, natomiast jej zarządzane opakowanie nazwiemy MClass, to wykonujemy następujące kroki: 1 w klasie MClass deklarujemy zmienną typu UClass *; 2 dla każdego konstruktora w UClass deklarujemy odpowiedni konstruktor w MClass, który korzystając z operatora new odwoła się do odpowiedniego konstruktora w UClass; 3 definiujemy destruktor w MClass, który usunie obiekt klasy UClass korzystając z operatora delete; 4 dla każdej funkcji składowej w UClass definiujemy funkcję w MClass, która jedynie wykonuje wywołanie funkcji w UClass, dokonując ew. koniecznych konwersji parametrów.

Opakowania kodu ANSI C++cd Które funkcje należy opakować : jeśli funkcja w niezarządzanej klasie jest prywatna, to nie ma potrzeby definiowania odpowieniej funkcji w klasie zarządzanej; nie ma konieczności definiowania opakowań dla funkcji, które nie będą wykorzystywane.

Opakowania kodu ANSI C++, przykład class UA { public: int f(int i) { return i+1; ; ref class A { private: UA *ua; ; public: A() { ua = new UA(); int f( int *i) { return ua->f(i); ~A() { delete ua; ;