ATD. Wykład 8. Programowanie (język C++) abstrakcyjny typ danych. Abstrakcyjne typy danych (ATD) Metody czysto wirtualne. Definicje i uwagi:

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

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

PARADYGMATY PROGRAMOWANIA Wykład 4

Wykład 1. Program przedmiotu. Programowanie (język C++) Literatura. Program przedmiotu c.d.:

Wyjątki. Wyjątki. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Politechnika Wrocławska

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

Wyjątki (exceptions)

Zaawansowane programowanie w języku C++ Programowanie obiektowe

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

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

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

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

referencje Wykład 2. Programowanie (język C++) Referencje (1) int Num = 50; zdefiniowano zmienną Num (typu int) nadając jej wartość początkową 50.

2.4 Dziedziczenie. 2.4 Dziedziczenie Przykłady programowania w C - kurs podstawowy

PARADYGMATY PROGRAMOWANIA Wykład 2

Plik klasy. h deklaracje klas

Język C++ wykład VIII

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

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

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

Identyfikacje typu na etapie. wykonania (RTTI)

Polimorfizm, metody wirtualne i klasy abstrakcyjne

PARADYGMATY PROGRAMOWANIA Wykład 3

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

TEMAT : KLASY DZIEDZICZENIE

TEMAT : KLASY POLIMORFIZM

Zad.30. Czy można utworzyć klasę, która implementuje oba interfejsy?

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Języki Programowania. Prowadząca: dr inż. Hanna Zbroszczyk. tel: Konsultacje: piątek:

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

C++ Przeładowanie operatorów i wzorce w klasach

Programowanie w języku C++

Programowanie obiektowe w języku

Konstruktor kopiujacy

C++ - [4-7] Polimorfizm

Programowanie w C++ Wykład 13. Katarzyna Grzelak. 4 czerwca K.Grzelak (Wykład 13) Programowanie w C++ 1 / 26

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

Efekty uboczne błędów

Programowanie obiektowe w C++ Wykład 12

Techniki Programowania wskaźniki

dr inż. Jarosław Forenc

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

Wyliczanie wyrażenia obiekty tymczasowe

Programowanie w C++ Wykład 6. Katarzyna Grzelak. kwiecień K.Grzelak (Wykład 6) Programowanie w C++ 1 / 40

Programowanie Obiektowe i C++

EGZAMIN PROGRAMOWANIE II (10 czerwca 2010) pytania i odpowiedzi

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

funkcje rekurencyjne Wykład 12. Podstawy programowania (język C) Funkcje rekurencyjne (1) Funkcje rekurencyjne (2)

Dzisiejszy wykład. Klasa string. wersja prosta wersja ze zliczaniem odwołań. Wyjątki Specyfikator volatile Semafory

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

hierarchie klas i wielodziedziczenie

Owad():waga(1),jadowitosc(false) {cout<<"konstruktor domyslny owada\n";}

Wstęp do programowania

Wstęp do Programowania 2

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

Programowanie obiektowe

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Wstęp do programowania

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Dziedziczenie jednobazowe, poliformizm

Szablon klasy std::list

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

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

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

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.

Programowanie obiektowe i C++ dla matematyków

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

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

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

class Student Deklaracja klasy Osoba: Deklaracja klasy Student:

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

Zmienne i struktury dynamiczne

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

Listy powiązane zorientowane obiektowo

Programowanie Obiektowe Ćwiczenie 4

Zaawansowane programowanie w C++ (PCP)

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

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Programowanie Obiektowew języku C++ Zadania L9

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

Dziedziczenie. Ogólna postać dziedziczenia klas:

DYNAMICZNE PRZYDZIELANIE PAMIECI

Typy zmiennych proste i złożone. Programowanie komputerów. Tablica. Złożone typy zmiennych. Klasa. Struktura

C-struktury wykład. Dorota Pylak

FUNKCJE WZORCOWE. Wykład 10. Programowanie Obiektowe (język C++) Funkcje wzorcowe wprowadzenie (2) Funkcje wzorcowe wprowadzenie (1)

Wprowadzenie do szablonów szablony funkcji

PROGRAMOWANIE OBIEKTOWE W C++ cz. 2. Dziedziczenie, operacje wej cia-wyj cia, przeładowanie operatorów.

Składnia C++ Programowanie Obiektowe, część 3 Mateusz Cicheński

Projektowanie obiektowe. Roman Simiński Wzorce projektowe Wybrane wzorce strukturalne

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 20 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 32

Wprowadzenie do szablonów szablony funkcji

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Szablony funkcji i szablony klas

Operacje wejścia/wyjścia odsłona pierwsza

Programowanie, część I

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

Programowanie - wykład 4

Podstawy programowania skrót z wykładów:

Podstawy algorytmiki i programowania - wykład 4 C-struktury

Transkrypt:

Programowanie (język C++) Wykład 8. ATD abstrakcyjny typ danych Tomasz Marks - Wydział MiNI PW -1- Tomasz Marks - Wydział MiNI PW -2- Metody czysto wirtualne Metody czysto wirtualne otrzymujemy inicjalizując je w klasie bazowej wartością 0, n.p.: class Class. virtual double Metoda ( ) = 0;. ; // Metoda jest czysto wirtualna Definicje i uwagi: Abstrakcyjne typy danych (ATD) 1. Klasa, w której zadeklarowano przynajmniej jedną metodę czysto wirtualną, nazywa się abstrakcyjnym typem danych (ATD). 2. Tworzenie obiektów klasy, która jest ATD, jest zabronione (ale wolno tworzyć wskaźniki i referencje do tej klasy). 3. ATD jest z załoŝenia przeznaczony do wykorzystania jako baza do definiowania klas pochodnych. 4. JeŜeli klasa pochodna nie nadpisuje (nie konkretyzuje) metody czysto wirtualnej, to teŝ jest ATD. 5. Metoda czysto wirtualna moŝe mieć w klasie bazowej implementację, z której mogą korzystać klasy pochodne. Istnienie takiej implementacji nie zmienia statusu "abstrakcyjności" klasy bazowej i wszystkich jej kolejnych pochodnych, aŝ do pochodnej, która metodę konkretyzuje. Tomasz Marks - Wydział MiNI PW -3- Tomasz Marks - Wydział MiNI PW -4-

Przykład ATD (1) class Zwierz const char* Imie; Zwierz ( const char * ); virtual void DajGłos ( ) = 0; // metoda DajGłos jest czysto wirtualna ; Zwierz :: Zwierz ( const char* im ) : Imie ( im ) void Zwierz :: DajGłos ( ) cout << endl << Imie << " się odzywa: "; class Pies : public Zwierz Pies ( const char * ); ; Przykład ATD (2) Pies :: Pies ( const char* im ) : Zwierz ( im ) void Pies :: DajGłos ( ) Zwierz::DajGłos( ); cout << "Hau! Hau!" << endl; Tomasz Marks - Wydział MiNI PW -5- Tomasz Marks - Wydział MiNI PW -6- class Kot : public Zwierz Kot ( const char * ); ; Przykład ATD (3) class Mysz : public Zwierz Mysz ( const char * ); ; Przykład ATD (4) Kot :: Kot ( const char* im ) : Zwierz ( im ) void Kot :: DajGłos ( ) Zwierz :: DajGłos( ); cout << "Miauuuuuuu" << endl; Mysz :: Mysz ( const char* im ) : Zwierz ( im ) void Mysz :: DajGłos ( ) Zwierz :: DajGłos( ); cout << "3.14, 3.14, 3.14" << endl; Tomasz Marks - Wydział MiNI PW -7- Tomasz Marks - Wydział MiNI PW -8-

Przykład ATD (5) int main ( ) //Zwierz ssak( "Rex" ); // BŁĄD! Zwierz jest ATD Pies P( "Azor" ); Kot K( "Mruczek" ); Mysz M( "Miki" ); P.DajGłos( ); // Azor się odzywa: Hau! Hau! K.DajGłos( ); // Mruczek się odzywa: Miauuuuuuu M.DajGłos( ); // Miki się odzywa: 3.14, 3.14, 3.14 Zoo[ 0 ] = &P; Zoo[ 1 ] = &K; Zoo[ 2 ] = &M; for ( int i = 0; i < 3; ++i ) Zoo[ i ] -> DajGłos( ); // Azor się odzywa: Hau! Hau! // Mruczek się odzywa: Miauuuuuuu // Miki się odzywa: 3.14, 3.14, 3.14 Przykład ATD (1a) class Zwierz const char* Imie; Zwierz ( const char *); virtual const char* Co ( ) = 0; // metoda Co jest czysto wirtualna virtual void DajGłos ( ) = 0; // metoda DajGłos jest czysto wirtualna ; Zwierz :: Zwierz ( const char* im ) : Imie ( im ) void Zwierz :: DajGłos ( ) cout << endl << Co( ) << Imie << " się odzywa: "; Tomasz Marks - Wydział MiNI PW -9- Tomasz Marks - Wydział MiNI PW -10- Przykład ATD (2a) struct Pies : public Zwierz const char* siersc; Pies ( const char *, const char* ); const char* Co ( ); ; Pies :: Pies ( const char* im, const char* s ) : Zwierz ( im ), siersc ( s ) const char* Pies :: Co ( ) return "pies"; void Pies :: DajGłos ( ) Zwierz :: DajGłos( ); cout << "Hau! Hau!" << endl; Tomasz Marks - Wydział MiNI PW -11- Przykład ATD (3a) struct Kot : public Zwierz const char* kolor; Kot ( const char*, const char* ); const char* Co ( ); ; Kot :: Kot ( const char* im, const char* kol ) : Zwierz ( im ), kolor ( kol ) const char* Kot :: Co ( ) return "kot"; void Kot :: DajGłos ( ) Zwierz :: DajGłos( ); cout << "Miauuuuuuu" << endl; Tomasz Marks - Wydział MiNI PW -12-

struct Mysz : public Zwierz int ogon; // [cm] Mysz ( const char*, int ); const char* Co ( ); ; Przykład ATD (4a) Mysz :: Mysz ( const char* im, int og ) : Zwierz ( im ), ogon( og ) const char* Mysz :: Co ( ) return "mysz"; void Mysz :: DajGłos ( ) Zwierz :: DajGłos( ); cout << "3.14, 3.14, 3.14" << endl; Tomasz Marks - Wydział MiNI PW -13- int main ( ) Pies P( "Azor", "krótka" ); Kot K( "Mruczek", "bury" ); Mysz M( "Miki", 10 ); Przykład ATD (5a) Zoo[ 0 ] = &P; Zoo[ 1 ] = &K; Zoo[ 2 ] = &M; for ( int i = 0; i < 3; ++i ) Zoo[ i ] -> DajGłos( ); switch ( * ( Zoo[ i ] -> Co( ) ) ) case 'p':... ( (Pies*) Zoo[ i ] ) -> siersc... case 'k':... ( (Kot*) Zoo[ i ] ) -> kolor... case 'm':... ( (Mysz*) Zoo[ i ] ) -> ogon << "cm"... Tomasz Marks - Wydział MiNI PW -14- DYNAMICZNA KONTROLA TYPU Tomasz Marks - Wydział MiNI PW -15- Przykład ATD (6a) Wirtualna metoda Co( ) umoŝliwiła nam zidentyfikowanie konkretnego typu obiektu dostępnego za pomocą wskaźnika klasy bazowej: for ( int i = 0; i < 3; ++i ) Zoo[ i ]->DajGłos( ); switch ( *Zoo[i]->Co( ) ) case 'p': cout << "sierść " << ((Pies*) Zoo[ i ]) -> siersc; break; case 'k': cout << "kolor " << ((Kot*) Zoo[ i ]) -> kolor; break; case 'm': cout << "ogon " << ((Mysz*) Zoo[ i ]) -> ogon << "cm"; // pies Azor się odzywa: Hau! Hau! // sierść krótka // kot Mruczek się odzywa: Miauuuuuuu // kolor bury // mysz Miki się odzywa: 3.14, 3.14, 3.14 // ogon 10cm Tomasz Marks - Wydział MiNI PW -16-

Przykład ATD (6b) Ten sam cel moŝe być osiągnięty przez uŝycie operatora typeid, chociaŝ w tym przypadku nie będzie moŝliwe zastosowanie instrukcji switch: for ( int i = 0; i < 3; ++i ) Zoo[ i ]->DajGłos( ); if ( typeid( *Zoo[ i ] ) == typeid( Pies ) ) cout << "siersc: " << ((Pies*)Zoo[ i])->siersc; else if ( typeid( *Zoo[ i ] ) == typeid( Kot ) ) cout << "kolor: " << ((Kot*)Zoo[ i ])->kolor; else if ( typeid( *Zoo[ i ] ) == typeid( Mysz ) ) cout << "ogon: " << ((Mysz*)Zoo[ i ])->ogon << "cm"; // pies Azor się odzywa: Hau! Hau! // sierść krótka // kot Mruczek się odzywa: Miauuuuuuu // kolor bury // mysz Miki się odzywa: 3.14, 3.14, 3.14 // ogon 10cm Tomasz Marks - Wydział MiNI PW -17- Operator typeid Gdybyśmy chcieli opisać operator typeid jako funkcję, to potrzebne by były następujące deklaracje: class type_info; const type_info& typeid ( NazwaTypu ); const type_info& typeid ( WyraŜenie ); gdzie type_info jest typem zdefiniowanym w bibliotece standardowej ( <typeinfo> ). Dokładniej naleŝałoby napisać: class type_info; const type_info& typeid ( NazwaTypu ) throw( ); const type_info& typeid ( WyraŜenie ) throw ( bad_type ); ale jeszcze nie znamy obsługi wyjątków, więc te szczegóły wyjaśnimy później. Tomasz Marks - Wydział MiNI PW -18- Klasa type_info w znacznej mierze zaleŝy od implementacji, ale główne aspekty zawiera poniŝsza specyfikacja: class type_info virtual ~type_info( ); // jest polimorficzne int operator== ( const type_info& ) const; // moŝna porównywać int operator!= ( const type_info& ) const; int before(const type_info& rhs) const; // porządek const char* name( ) const; // nazwa typu... private: type_info( const type_info& ); // kopiowanie zabronione type_info& operator= ( const type_info& );... ; Przykład ATD (1b) Z punktu widzenia procesu projektowania hierarchii klas, zarówno wykorzystanie metody Co( ) jak i operatora typeid nie jest eleganckie ( patrz Stroustrup [1] str. 464 ). PrzecieŜ ten sam cel moŝna osiągnąć wprowadzając metodę wirtualną Opis( ): class Zwierz const char* Imie; Zwierz ( const char *); virtual const char* Co ( ) = 0; virtual void DajGłos ( ) = 0; // metoda DajGłos jest czysto wirtualna virtual void Opis ( ) = 0; // kolejna metoda czysto wirtualna ; const char* Pies :: Opis ( ) cout << "sierść" << siersc; const char* Kot :: Opis ( ) cout << "kolor " << kolor; const char* Mysz :: Opis ( ) cout << "ogon " << ogon << "cm"; Tomasz Marks - Wydział MiNI PW -19- Tomasz Marks - Wydział MiNI PW -20-

Metoda Opis( ) pozwala napisać: Przykład ATD (6c) for ( int i = 0; i < 3; ++i ) Zoo[ i ]->DajGłos( ); Zoo[ i ]->Opis( ); // pies Azor się odzywa: Hau! Hau! // sierść krótka // kot Mruczek się odzywa: Miauuuuuuu // kolor bury // mysz Miki się odzywa: 3.14, 3.14, 3.14 // ogon 10cm WIRTUALNY DESTRUKTOR Tomasz Marks - Wydział MiNI PW -21- Tomasz Marks - Wydział MiNI PW -22- Przykład ATD (1b) śeby prześledzić proces destrukcji zdefiniujemy destruktor w klasie bazowej class Zwierz const char* Imie; Zwierz ( const char *); ~Zwierz ( ); virtual const char* Co ( ) = 0; virtual void DajGłos ( ) = 0; virtual void Opis ( ) = 0; ; Zwierz::~Zwierz( ) cout << endl << "o imieniu " << Imie << endl; i analogicznie dla klas pochodnych: Pies::~Pies( ) cout << endl << "Znika pies"; Kot::~Kot( ) cout << endl << "Znika kot"; Mysz::~Mysz( ) cout << endl << "Znika mysz"; Tomasz Marks - Wydział MiNI PW -23- int main ( ) Pies P( "Azor", "krótka" ); Kot K( "Mruczek", "bury" ); Mysz M( "Miki", 10 ); Przykład ATD (5a) Zoo[ 0 ] = &P; Zoo[ 1 ] = &K; Zoo[ 2 ] = &M; // Znika mysz // o imieniu Miki // Znika kot // o imieniu Mruczek // Znika pies // o imieniu Azor Tomasz Marks - Wydział MiNI PW -24-

int main ( ) Przykład ATD (5d) int main ( ) Przykład ATD (5e) Zoo[ 0 ] = new Pies( "Azor", "krótka" ); Zoo[ 1 ] = new Kot( "Mruczek", "bury" ); Zoo[ 2 ] = new Mysz M( "Miki", 10 ); Zoo[ 0 ] = new Pies( "Azor", "krótka" ); Zoo[ 1 ] = new Kot( "Mruczek", "bury" ); Zoo[ 2 ] = new Mysz M( "Miki", 10 ); for ( int i=0; i<3; ++i ) delete Zoo[ i ]; Oczywiście teraz, jeśli nie spróbujemy usunąć obiektów, to destruktory się "nie odezwą". // o imieniu Azor // o imieniu Mruczek // o imieniu Miki Jak widać, uruchamiany będzie tylko destruktor zdefiniowany w klasie bazowej. Tomasz Marks - Wydział MiNI PW -25- Tomasz Marks - Wydział MiNI PW -26- Przykład ATD (1b) Aby spowodować uruchamianie destruktorów klas pochodnych, trzeba zdefiniować destruktor klasy bazowej jako wirtualny: class Zwierz const char* Imie; Zwierz ( const char *); virtual ~Zwierz ( ); virtual const char* Co ( ) = 0; virtual void DajGłos ( ) = 0; virtual void Opis ( ) = 0; ; Zwierz::~Zwierz( ) cout << endl << "o imieniu " << Imie << endl; w klasach pochodnych bez zmian: Pies::~Pies( ) cout << endl << "Znika pies"; Kot::~Kot( ) cout << endl << "Znika kot"; Mysz::~Mysz( ) cout << endl << "Znika mysz"; W efekcie otrzymamy: int main ( ) Przykład ATD (5e) Zoo[ 0 ] = new Pies( "Azor", "krótka" ); Zoo[ 1 ] = new Kot( "Mruczek", "bury" ); Zoo[ 2 ] = new Mysz M( "Miki", 10 ); for ( int i=0; i<3; ++i ) delete Zoo[ i ]; // Znika pies // o imieniu Azor // Znika kot // o imieniu Mruczek // Znika mysz // o imieniu Miki Tomasz Marks - Wydział MiNI PW -27- Tomasz Marks - Wydział MiNI PW -28-

Przeciwdziałanie błędom wykonania programu (1) OBSŁUGA WYJĄTKÓW double& Vector :: operator [ ] ( int i ) return V[ i ]; // operacja niebezpieczna!!! double& Vector :: operator [ ] ( int i ) if ( i >= 0 && i < Size ) return V[ i ]; DisplayMessage( "komunikat o błędzie" ); // fukcja systemowa lub własna exit(1); // funkcja standardowa double& Vector :: operator [ ] ( int i ) assert ( i >= 0 && i < Size ) // makro assert return V[ i ]; double& Vector :: operator [ ] ( int i ) if ( i < 0 i >= Size ) throw xcp_scope( i ); // odrzucenie wyjątku return V[ i ]; Tomasz Marks - Wydział MiNI PW -29- Tomasz Marks - Wydział MiNI PW -30- Przeciwdziałanie błędom wykonania programu (2) // vector.h struct xcp_memory ; // zewnętrzna (wzgl. Vector) klasa pomocnicza class Vector int Size, Nr; double *V; static int DefSize, VCounter; void Init ( int = 0, double = 0, double * = 0 ); Vector ( ); Vector ( int size, double val = 0 ); Vector ( int size, double arr[ ] );. struct xcp_scope // wewnętrzna (w Vector) klasa pomocnicza int index; xcp_scope ( int ); ;. ; Przeciwdziałanie błędom wykonania programu (3) // vector.cpp // implementacja konstruktora klasy xcp_scope Vector :: xcp_scope :: xcp_scope ( int i ) : index ( i ) // metoda prywatna (wersja oryginalna) void Vector :: Init ( int s, double val, double tab[ ] ) Nr = ++VCounter; if ( s <= 0 ) s = DefSize; V = new double [ s ]; if (! V ) Size = 0; return; Size = s; for ( s = 0; s < Size; ++s ) V [ s ] = tab? tab [ s ] : val; Tomasz Marks - Wydział MiNI PW -31- Tomasz Marks - Wydział MiNI PW -32-

Przeciwdziałanie błędom wykonania programu (4) // metoda prywatna (wersja zmodyfikowana) void Vector :: Init ( int s, double val, double tab[ ] ) if ( VCounter > 7 ) throw "Za duzo wektorow!"; Nr = ++VCounter; if ( s < 0 ) throw "Blad konstrukcji!"; if ( s <= 0 ) s = DefSize; try V = new double [ s ]; catch ( ) throw xcp_memory ( ); if (! V ) throw xcp_memory ( ); Size = s; for ( s = 0; s < Size; ++s ) V [ s ] = tab? tab [ s ] : val; Przeciwdziałanie błędom wykonania programu (5) #include "vector.h" void main ( ) Vector w( 4 ); for ( int i = -1; i < 7; i++ ) try cout << endl << "i = " << i << " "; Vector z( i ); w[ i ] = i; cout << "w[" << i << "] = " << w[ i ]; catch ( const char * str ) cout << str; catch ( xcp_memory ) cout << "Brak pamieci"; catch ( Vector :: xcp_scope ex ) cout << "Odrzucono indeks " << ex.index; Tomasz Marks - Wydział MiNI PW -33- Tomasz Marks - Wydział MiNI PW -34- Przeciwdziałanie błędom wykonania programu (6) Program wyświetli: i = -1 Blad konstrukcji! i = 0 w[ 0 ] = 0 i = 1 w[ 1 ] = 1 i = 2 w[ 2 ] = 2 i = 3 w[ 3 ] = 3 i = 4 Odrzucono indeks 4 i = 5 Odrzucono indeks 5 i = 6 Za duzo wektorow! 1. Składnia instrukcji try-catch: Obsługa wyjątków [1] try // początek bloku try... // koniec bloku try catch (.. ) // 1. blok catch catch (.. ) // 2. blok catch... catch (.. ) // ostatni blok catch blok try wraz ze wszystkimi następującymi po nim blokami catch stanowi składniowo jedną całość, którą nazywamy instukcją try-catch Tomasz Marks - Wydział MiNI PW -35- Tomasz Marks - Wydział MiNI PW -36-

Obsługa wyjątków [2] Obsługa wyjątków [3] 2. Bloki catch są nazywane procedurami obsługi wyjątków. 3. KaŜda procedura obsługi wyjątków ma określony typ sytuacji wyjątkowej, która ją aktywizuje. 4. Zgłoszenie sytuacji wyjątkowej (throw) podczas wykonywania bloku try skutkuje przekazaniem pewnego obiektu do odpowiedniej procedury obsługi. 5. Dopasowanie wyraŝenia throw do procedury obsługi polega na porównaniu typu wartości wyraŝenia throw z typami ( parametrów ) określonymi dla kolejnych procedur obsługi. 6. Dopasowanie uznane będzie za pomyślne, jeŝeli spełniony zostanie jeden z trzech warunków: (i) oba typy są ściśle zgodne; (ii) typ określony dla parametru procedury obsługi jest publiczną klasą bazową klasy obiektu będącego wartością wyraŝenia throw; (iii) moŝliwe jest standardowe przekształcenie typu wartości wyraŝenia throw, będącej wskaźnikiem, na typ wskaźnikowy parametru procedury. Po pozytywnym rozpoznaniu jednego z warunków (i), (ii), (iii), dalsze frazy catch nie będą analizowane. Tomasz Marks - Wydział MiNI PW -37- Tomasz Marks - Wydział MiNI PW -38- Obsługa wyjątków [4] 7. JeŜeli dopasowanie nie da pozytywnego rezultatu, t.zn. Ŝadna procedura catch nie zostanie uruchomiona, to dana instrukcja try-catch będzie uznana za zakończoną i nastąpi sprawdzenie, czy w aktualnie wykonywanej funkcji jest blok try zawierający daną instukcję try-catch. JeŜeli taki blok istnieje, to wykonana zostanie próba dopasowania rozpatrywanygo wyjątku do występujących po nim procedur obsługi. JeŜeli taki blok nie istnieje, to wykonanie funkcji zostanie zakończone i odpowiedni blok będzie poszukiwany w funkcji wywołującej tę, w której został odrzucony wyjątek itd. itd. W skrajnym przypadku, jeŝeli dopasowanie nie zostanie zrealizowane w obrębie funkcji main(), obsługę wyjątku przejmie systemowa procedura obsługi wyjątków, która wyświetli odpowiedni komunikat i zakończy działanie programu. Obsługa wyjątków [5] 8. Zapis procedury obsługi nie musi zawierać nazwy przyjmowanego obiektu (parametru). Nazwa jest konieczna jedynie w sytuacji, gdy zachodzi rzeczywista potrzeba uŝycia wartości tego parametru. 9. Trzykropek pozwala określić procedurę wychwytującą wyjątki wszystkich typów. 10. Wewnątrz procedury obsługi (catch) moŝna uŝyć frazy throw z pustym wyraŝeniem throw; Skutkuje to przekazaniem wyjątku do zewnętrznego bloku try. W innych kontekstach uŝycie pustego wyraŝenia throw jest błędem. Tomasz Marks - Wydział MiNI PW -39- Tomasz Marks - Wydział MiNI PW -40-

Obsługa wyjątków [6] 11. Deklaracja funkcji moŝe zawierać klauzulę, która stanowi ograniczenie zbioru sytuacji wyjątkowych zgłaszanych bezpośrednio lub pośrednio przez tę funkcję: void fun1 (.. ); // moŝe zgłaszać dowolne wyjątki long fun2 (.. ) throw (const char*, xcp_scope&); // moŝe zgłaszać wyjątki wymienionych typów double fun3 (.. ) throw ( ); // nie moŝe zgłaszać Ŝadnych wyjątków Naruszenie zadeklarowanej specyfikacji spowoduje błąd wykonania programu. Koniec wykładu 8. 12. Klauzula ograniczenia zbioru sytuacji wyjątkowych nie jest uwaŝana za element określenia typu funkcji ( tzn. nie wchodzi w skład deskryptora funkcji ). Tomasz Marks - Wydział MiNI PW -41- Tomasz Marks - Wydział MiNI PW -42-