Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

PB161 PB161 – Programování v jazyce C++ Objektově Orientované Programování STL algoritmy, Funktory, Výjimky STL algs, Výjimky, Functor 3.11.2014 1.

Podobné prezentace


Prezentace na téma: "PB161 PB161 – Programování v jazyce C++ Objektově Orientované Programování STL algoritmy, Funktory, Výjimky STL algs, Výjimky, Functor 3.11.2014 1."— Transkript prezentace:

1 PB161 PB161 – Programování v jazyce C++ Objektově Orientované Programování STL algoritmy, Funktory, Výjimky STL algs, Výjimky, Functor

2 PB161 Organizační - zvané přednášky Juraj Michálek (YSoft) Jiří Weiser (Laboratoř Paradise) - C++11 STL algs, Výjimky, Functor

3 PB161 STL Algoritmy STL algs, Výjimky, Functor

4 PB161 STL zavádí nové koncepty 1.Kontejnery ●objekty, které uchovávají jiné objekty bez ohledu na typ ●kontejnery různě optimalizovány pro různé typy úloh ●např. std::string (uchovává pole znaků) ●např. std::list (zřetězený seznam) 2.Iterátory ●způsob (omezeného) přístupu k prvkům kontejneru ●např. std::string.begin() ●přetížené operátory ++ pro přesun na další prvek atd. 3.Algoritmy ●běžné operace vykonané nad celými kontejnery ●např. sort(str.begin(), str.end()) STL algs, Výjimky, Functor Přednáška

5 PB161 STL Algoritmy Standardní metody pracující nad kontejnery Obsahuje často používané operace (hledání, řazení…) Mohou kontejner číst nebo i měnit Často využívají (jako argument) iterátory STL algs, Výjimky, Functor // sort algorithm example from #include using namespace std; int main () { vector myvector; // fill vector by values sort (myvector.begin(), myvector.end()); return 0; }

6 PB161 Algoritmy - dokumentace STL algs, Výjimky, Functor Funkce dostupné v Ukázka syntaxe na for_each 6

7 PB161 Základní dostupné STL algoritmy Vyhledávání, statistika (nemodifikují cílový kontejner) find(), search(), count()… Modifikují cílový kontejner copy(), remove(), replace(), transform() Aplikace uživatelské funkce for_each() – (typicky) nemodifikuje původní kontejner transform() – (typicky) modifikuje obsah kontejneru Řadící sort() vhodný řadící algoritmus automaticky vybrán dle typu kontejneru Spojování rozsahů, Minimum, maximum… A spousta dalších STL algs, Výjimky, Functor

8 PB161 STL algs, Výjimky, Functor Převzato z

9 PB161 STL algs, Výjimky, Functor Převzato z

10 PB161 STL algoritmy – find STL algs, Výjimky, Functor #include using std::cout; using std::endl; int main() { std::list myList; myList.push_back(1);myList.push_back(2);myList.push_back(3); myList.push_back(4);myList.push_back(5); // 1, 2, 3, 4, 5 std::list ::iterator iter; // Find item with value 4 if ((iter = std::find(myList.begin(), myList.end(), 4)) != myList.end()) { cout << *iter << endl; } // Try to find item with value 10 if ((iter = std::find(myList.begin(), myList.end(), 10)) != myList.end()) { cout << *iter << endl; } else cout << "10 not found" << endl; return 0; }

11 PB161 STL algoritmy – for_each a transform STL algs, Výjimky, Functor #include using std::cout; using std::endl; int increase10(int value) { return value + 10; } void print(int value) { cout << value << endl; } int main() { std::list myList; // … fill something into myList // Apply function to range (typically non-modifying) std::for_each(myList.begin(), myList.end(), print); // Apply function to range (will work only for integers) (modifying) std::transform(myList.begin(),myList.end(),myList.begin(),increase10); return 0; } for_each může také modifikovat kontejner Pokud je hodnota předávána referencí print(int& value) Pro modifikaci používejte ale raději transform

12 PB161 STL algoritmy – callback funkce Některé algoritmy berou jako parametr funkci ●aplikují ji na prvky kontejneru Může být klasická C funkce (např. print() ) Může být static metoda objektu (viz. dále) Může být objekt s přetíženým operátorem() ●tzv. functor, viz dnes později Může být lambda (C++11, pozdější přednáška) STL algs, Výjimky, Functor std::for_each(myList.begin(), myList.end(), print); template Function for_each(InputIterator first, InputIterator last, Function f) { for ( ; first!=last; ++first ) f(*first); return f; }

13 PB161 STL algoritmy – sort STL algs, Výjimky, Functor // sort algorithm example from #include using namespace std; bool myfunction (int i,int j) { return (i

14 PB161 Funkční objekty STL algs, Výjimky, Functor

15 PB161 Funkční objekt - motivace Z C/C++ jsou známé tzv. callback funkce ●pomocí funkčního ukazatele je možné předat jako parametr ukazatel na funkci, která je později zavolána ●používá se například u STL algoritmů ● std::for_each(l.begin(),l.end(), print); Co když chceme přičítat pomoc std::transform číslo 10? ●vytvoříme funkci int add10(int value){return value+10;} ● std::transform(l.begin(),l.end(),l.begin(),add10); Co když chceme přičítat libovolné číslo? STL algs, Výjimky, Functor

16 PB161 Funkční objekt – Functor Objekt, který může zavolán, jako by to byla běžná funkce ●dosáhneme pomocí přetíženého operátoru () ● A prom; prom(5); Operátor () musíme přetížit pro všechny potřebné typy a počty argumentů ●tj. pro každou funkci, kterou chceme functorem nahradit ●jeden functor může nahrazovat několik funkcí (jak?) Pokud se pokusíme použít objekt jako functor a neexistuje odpovídající přetížený operátor () ●error: no match for call to '(typ_objektu) (typ_argumentů)' ●stl_algo.h:4688:2: error: no match for call to '(A) (int&)' STL algs, Výjimky, Functor

17 PB161 Functor - ukázka STL algs, Výjimky, Functor #include class CAddX { int m_whatAdd; public: CAddX(int whatAdd) : m_whatAdd(whatAdd) {} void set(int whatAdd) { m_whatAdd = whatAdd; } int operator () (int value) { return value + m_whatAdd; } }; int main() { std::list myList; myList.push_back(1); myList.push_back(2); myList.push_back(3); myList.push_back(4); CAddX variableAdder(3); // variableAdder is functor object, now adding number 3 transform(myList.begin(), myList.end(), myList.begin(), variableAdder); // change added value variableAdder.set(101); transform(myList.begin(), myList.end(), myList.begin(), variableAdder); return 0; } Nyní přičítač trojky Nyní přičítač stojedničky

18 PB161 Functory – vhodnost použití Výhodou je možnost uchovávat (a měnit) stav functoru ●u funkcí bychom museli použít globální proměnné Functor může být výrazně rychlejší než funkce ●překladač může vložit kód functoru namísto volání ●u funkčních ukazatelů (callback) není možné Využívá myšlenek z funkcionálním programování ●současné imperativní jazyky mají podporu pro některé funkční prvky ●Functor, delegates a lambda výrazy... (C++11, C#...) STL algs, Výjimky, Functor

19 PB161 Příklad - kompozice funktorů Aplikace série funkcí na zadaný argument Např. pseudozápis 'a(b(c(d(5))))' znamená, že funkce a, b, c a d jsou aplikovány na argument 5. Úkolem je vytvořit program umožňující vytvářet (aritmetické) funkce složené z jednodušších funktorů Definice vhodného rozhraní a využití dědičnosti STL algs, Výjimky, Functor

20 PB161 Hierarchie STL algs, Výjimky, Functor UnaryFunction i FunctionCompositor mají přetížený operátor () a budou použity jako functory

21 PB161 STL algs, Výjimky, Functor class UnaryFunction { public: virtual ~UnaryFunction() {} virtual int operator() (int arg) const = 0; }; class UnaryNumericFunction : public UnaryFunction { public: UnaryNumericFunction(int rightOperand) : rightOperand_m(rightOperand) {} virtual int rightOperand() const { return rightOperand_m; } virtual void setRightOperand(int r) { rightOperand_m = r; } private: int rightOperand_m; }; class Adder : public UnaryNumericFunction { public: Adder(int r) : UnaryNumericFunction(r) {} int operator() (int arg) const { return arg + rightOperand(); } }; class Multiplier : public UnaryNumericFunction { public: Multiplier(int r) : UnaryNumericFunction(r) {} int operator() (int arg) const { return arg * rightOperand(); } }; Přetížíme operátor () pro aplikaci unární funkce Numerická unární funkce je functor s parametrizací v rightOperand_m V přetiženém operátoru () přičítáme Parametrizace functoru

22 PB161 STL algs, Výjimky, Functor // Function for deallocation void delete_ptr(UnaryFunction* ptr) { delete ptr; } class FunctionCompositor { public: FunctionCompositor() {} ~FunctionCompositor() { // Use for_each algorithm to deallocate separate functions std::for_each(functions_m.begin(), functions_m.end(), delete_ptr); } void appendFunction(UnaryFunction* fn) { functions_m.push_back(fn); } void prependFunction(UnaryFunction* fn) { functions_m.push_front(fn); } int operator() (int arg) { typedef std::list ::iterator iterator; for (iterator it = functions_m.begin(); it != functions_m.end(); ++it) { UnaryFunction* fnc = *it; // Get particular function arg = (*fnc)(arg); // Apply it on argument } return arg; } private: std::list functions_m; }; Parametrizace functoru probíhá přidáváním unárních funkcí Aplikací functoru pomocí operátoru () postupně zavoláme všechny obsažené funkce

23 PB161 Použití functorů STL algs, Výjimky, Functor #include int main() { FunctionCompositor comp; comp.prependFunction(new Adder(10)); comp.prependFunction(new Multiplier(2)); comp.prependFunction(new Adder(-5)); comp.prependFunction(new Adder(2)); int number = 0; std::cin >> number; std::cout << comp(number) << std::endl; } Vytváříme functor comp Vytváříme functor typu Adder (a další) a vkládáme do comp Aplikujeme functor comp

24 PB161 Výjimky (Exceptions) STL algs, Výjimky, Functor

25 PB161 Obsluha chyby – bez výjimek STL algs, Výjimky, Functor int foo(std::string name) { int status = 0; Person person(name); if (status == 0) { if (person.isValidName()) { cout << "Valid person " << person.getName() << endl; } else status = -1; // signalize problem with name } if (status == 0) { // Still no problem? std::string message; message = "My favourite person is "; message += person.getName(); cout << message << endl; } if (status == 0) { // Still no problem? //... do something else } if (status != 0) { // Some problem? //... report problem, roll back info.... } return status; } Proměnná s hodnotou chyby (0 == OK) Test, zda se nevyskytla chyba V případě chyby nastav status Každý další logický blok kódu obalen testem na OK Vrať informaci o průběhu Udělej něco v reakci na problém

26 PB161 Výjimky – motivace Výskyt situace, kterou je potřeba okamžitě řešit ●nedostatek paměti ●nepovolený přístup do paměti ●dělení nulou Může nastat kdekoli v kódu a může být řešitelné ●uvolníme nepotřebnou paměť a zkusíme znovu ●vypíšeme varování uživateli a nulou dál nedělíme Zároveň ale není praktické mít reagující kód na v každé metodě ●nedostatečná paměť může nastat kdekoli STL algs, Výjimky, Functor

27 PB161 Výjimky - syntaxe Označení oblasti kde zachytávat výjimku ●klíčové slovo try Zachycení výjimky ●klíčové slovo catch ●jeden nebo více bloků ●specifikace objektu výjimky typicky jako reference (Vyvolání výjimky) ●klíčové slovo throw STL algs, Výjimky, Functor try { // … some code throw std::logic_error("Problem"); // … some code (not executed) } catch (std::logic_error& ex) { // … handle somehow exception cout << ex.what() << endl; }

28 PB161 Výjimky (Exception) - princip 1.V případě výskytu problému se vyvolá výjimka objekt obsahující informaci o problému můžeme vyvolat i vývojář programově (throw) 2.Výjimka postupně “stoupá” volajícími funkcemi (callstack), dokud ji někdo nezachytí 3.Výjimka je zachycena obslužným blokem specifikuje, v jaké části kódu a jaké výjimky zachytávat try/catch blok 4.Na základě výjimky proběhne programová reakce ukončení programu výpis varování uživateli exception handling STL algs, Výjimky, Functor

29 PB161 Ukázka STL algs, Výjimky, Functor int main() { cout << "Code before exception handling" << endl; try { Person p1("Pepa Novak"); // No problem Person p2(""); p1.print(); p2.print(); } catch (WrongNameExceptionExt& ex) { cout << "WrongNameExceptionEx: " << ex.what(); } cout << "Continuing after block with exception handling"; return 0; } class Person { std::string m_name; public: Person(const std::string name) : m_name(name) { if (m_name.size() == 0) throw WrongNameExceptionExt("Invalid empty name"); } void print() const { cout << m_name << endl; } }; Výjimka vyvolána Výjimka zachycena, obsloužena a zaniká Kód nebude vykonán Program pokračuje

30 PB161 Datový typ výjimky Primitivní datové typy ●např. int, char… ● throw 1; catch (int ex) { } ● throw 'e'; catch (char ex) { } Struktury, třídy ●struktury nebo třídy definované programátorem ● MyStructException ex; throw ex; ● catch (MyStructException& ex) { } Potomci std::exception ●nejčastěji potomci std::logic_error nebo std::runtime_error ● class MyException : public std::logic_error { ● catch (std::logic_error& ex) {} STL algs, Výjimky, Functor

31 PB161 STL algs, Výjimky, Functor int main() { cout << "Code before exception handling“; try { foo(4); // throw exception cout << "Will not be printed"; } catch (int ex) { cout << "Integer exception: " << ex; } catch (char ex) { cout << "Char exception: " << ex; } catch (MyStructException& ex) { cout << "Struct exception : " << ex.reason; } catch (MyException& ex) { cout << "class MyException : " << ex.what(); } cout << "Continuing after block with EH“; return 0; } #include using std::cout; using std::endl; struct MyStructException { std::string reason; int someValue; }; class MyException : public std::invalid_argument { public: MyException(const std::string& reason = "") : std::invalid_argument(reason) {} }; void foo(int what) { if (what == 1) throw 1; if (what == 2) throw 'e'; if (what == 3) { MyStructException ex; ex.reason = "Just testing"; ex.someValue = -1; throw ex; } if (what == 4) throw MyException("Just testing"); } Vyhazuje různé typy výjimek podle what foo(1) foo(2) foo(3) foo(4)

32 PB161 Standardní výjimky Výjimky jsou vyvolávané ●jazykovými konstrukcemi (např. new ) ●funkcemi ze standardní knihovny (např. STL algoritmy) ●uživatelským kódem (výraz throw ) Základní třída std::exception ● #include ●metoda exception::what() pro získání specifikace důvodu Dvě základní skupiny standardních výjimek ● std::logic_error – chyby v logice programu ●např. chybný argument, čtení za koncem pole… ● std::runtime_error – chyby způsobené okolním prostředím ●např. nedostatek paměti (bad_alloc) ●v konstruktoru můžeme specifikovat důvod ( std::string ) ●http://www.cplusplus.com/reference/std/stdexcept/http://www.cplusplus.com/reference/std/stdexcept/ STL algs, Výjimky, Functor

33 PB161 new a zachycení výjimky STL algs, Výjimky, Functor // Allocate A object dynamically // If fail, std::bad_alloc exception is thrown A* pTest2 = 0; try { pTest2 = new A(20); pTest2->print(); // no need to test pTest2 != NULL delete pTest2; } catch (std::bad_alloc& ex) { cout << "Fail to allocate memory"; } class A { int m_value; public: A(int value) : m_value(value) {} void print() const {cout << m_value << endl; } };

34 PB161 Vlastní výjimky - třídy STL algs, Výjimky, Functor std::exception nemá konstruktor s možností specifikace důvodu (řetězec) Dědíme typicky z logic_error a runtime_error ●mají konstruktor s parametrem důvodu ( std::string ) Nebo jejich specifičtějších potomků ●např. std::invalid_argument pro chybné argumenty 34

35 PB161 Vlastní výjimky - ukázka STL algs, Výjimky, Functor class WrongNameExceptionExt : public std::invalid_argument { std::string m_wrongName; public: WrongNameExceptionExt(const std::string& reason = "", const std::string name = "") : std::invalid_argument(reason), m_wrongName(name) {} const std::string getName() const { return m_wrongName; } ~WrongNameExceptionExt() throw () {} }; Jméno výjimky rodič výjimky zvolte co nejspecifičtěji Výjimka může nést dodatečné informace dle našich potřeb Konstruktor pro specifikace informací o výjimce. Inicializuje i předka. Můžeme přidat vlastní dodatečné metody Destruktor – nutné pokud máme atributy, které mají také destruktor

36 PB161 Zachycení výjimek – využití dědičnosti Výjimky mohou tvořit objektovou hierachii ●typicky nějací potomci std::exception Při zachytávání můžeme zachytávat rodičovský typ ●nemusíme chytat výjimky podle nejspecifičtějšího typu ●obslužný kód může reagovat na celou třídu výjimek ●např. zachytává výjimku typu std::runtime_error a všechny potomky STL algs, Výjimky, Functor class MyException : public std::invalid_argument; int main() { try { throw MyException(“Test”); } catch (std::invalid_argument& ex) { cout << “invalid argument : " << ex.what(); } return 0; } Vyvoláme MyException, chytáme invalid_argument

37 PB161 Pořadí vyhodnocování catch klauzulí Dle pořadí v kódu ●pokud je více klauzulí, postupně se hledá klauzule s odpovídajícím datovým typem ●klauzule “výše” budou vyhodnoceny dříve Vhodné řadit od nejspecifičtější po nejobecnější ●nejprve potomci, potom předci ●jinak se pozdější specifičtější nikdy neuplatní Kompilátor nás upozorní warningem ●warning: exception of type 'WrongNameException' will be caught by earlier handler for 'std::logic_error' STL algs, Výjimky, Functor

38 PB161 Pořadí zachycení – ukázka problému STL algs, Výjimky, Functor class WrongNameExceptionExt : public std::invalid_argument; class Person; int main() { cout << "Code before exception handling" << endl; try { Person p2(""); // Exception WrongNameExceptionExt thrown } catch (std::invalid_argument & ex) { cout << "Exception from group std::logic_error : " << ex.what(); } catch (WrongNameExceptionExt& ex) { cout << "WrongNameExceptionExt: " << ex.what() << " " << ex.getName(); } cout << "Continuing after block with exception handling" << endl; return 0; } Není nikdy provedeno – všechny výjimky WrongNameExceptionExt jsou zachyceny jako std::invalid_argument

39 PB161 Zachycení a znovuposlání výjimky Někdy zjistíme že ji nedokážeme obsloužit ●nebo chceme ještě provést obsluhu jinde Výjimka typicky zaniká na konci bloku catch, který ji zachytí ●pokud neurčíme jinak Výjimku můžeme poslat dál ●do bloku catch umístíme throw bez argumentů ●pošle dál aktuální výjimku STL algs, Výjimky, Functor

40 PB161 Znovuposlání výjimky - ukázka STL algs, Výjimky, Functor class WrongNameExceptionExt : public std::invalid_argument; class Person; void foo() { try { Person p1("Pepa Novak"); // No problem Person p2(""); // Exception thrown } catch (WrongNameExceptionExt& ex) { cout << "WrongNameExceptionExt: " << ex.what() << endl; throw; // Let it propagate further } int main() { try { foo(); } catch (std::logic_error& ex) { cout << "Exception std::logic_error : " << ex.what(); } return 0; } Výjimka odchycena, ale poslána dál Výjimka znovu zachycena a finálně zpracována. Prázdné jméno způsobí výjimku

41 PB161 Zachycení všech výjimek catch(…) Klauzule catch(…){} zachytí většinu běžných výjimek ●závisí na překladači, někdy i nezotavitelné jako SIGSEGV (VS6) ●není přístup k objektu výjimky V běžném kódu zachytávejte pouze výjimky, které umíte zpracovat ●pokud opravdu nevíte že potřebujete zachytit všechny ●okolní kód může být schopen na výjimku reagovat lépe STL algs, Výjimky, Functor

42 PB161 Zachycení všech výjimek catch(…) V některých případech je naopak velmi vhodné zachytávat všechny výjimky ●výjimky by neměly být propagovány mimo váš modul ●není dána přesná realizace objektu výjimky, záleží na překladači ●kód přeložený jiným může spadnout při ošetření Obalení těla funkce main() ●zabrání neřízenému pádu programu Obalení těla destruktoru ●destruktor by neměl nikdy vyvolat výjimku (kdo by ošetřil?) Obalení těla callback funkce ●výjimka z naší callback funkce jde do kontextu uživatele callbacku STL algs, Výjimky, Functor

43 PB161 catch(…) pro logování Využívá se např. v kombinaci se znovuvyvoláním pro uložení logu o problému STL algs, Výjimky, Functor int main() { try { foo(); } catch (...) { cerr << " error in " << __FILE__ << __LINE__ ; throw; } return 0; }

44 PB161 Nezachycená výjimka STL algs, Výjimky, Functor Může nastat když ●neobsluhujeme výjimky vůbec ●nastane mimo blok s obsluhou výjimky Následuje ukončení programu 44 #include int main() { // 1. Segmentation fault (SIGSEGV) int array[10]; array[100] = 1; // 2. Division by zero (SIGFPE) float result = 10 / 0; // 3. Own uncoght exception throw std::logic_error("Test"); return 0; }

45 PB161 Seznam vyvolávaných výjimek Můžeme specifikovat seznam výjimek, které daná metoda může vyvolat (exception-specification) ●informace pro uživatele metody (co hlídat a zkoušet odchytávat) ●informace pro překladač (možné optimalizace, ale viz. dále) Pokud metoda vyvolá jinou výjimku než deklarovanou ●je zavolána funkce std::unexpected() ●defaultní implementace přeruší program ●můžeme upravit set_unexpected(naše_obslužná_fce) Pozor na odlišnost od Javy! ●u Javy kontroluje překladač (nedovolí vyvolávat jinou výjimku) ●u C++ kontroluje až běhové prostředí ( pomocí unexpected()) Problematické, spíše nepoužívejte ●viz. diskuze ●vývojáře nekontroluje (až za běhu), překladači téměř nepomáhá STL algs, Výjimky, Functor

46 PB161 Seznam vyvolávaných výjimek - ukázka STL algs, Výjimky, Functor struct MyStructException; class MyException : public std::invalid_argument; void foo(int what) throw(int, MyException) { if (what == 1) throw 1; if (what == 2) throw 'e'; if (what == 3) { MyStructException ex; ex.reason = "Just testing"; ex.someValue = -1; throw ex; } if (what == 4) throw MyException("Just testing"); } // Note: will compile even when foo() // has different exception-specification void foo2(int what) throw(int) { foo(what); } void handleUnexpected () { std::cerr << "unexpected exception thrown"; // throws exception with int type //(allowed in exception-specification) throw -1; //... or e.g., terminate //std::terminate(); } #include using std::cout; using std::endl; int main() { std::set_unexpected(handleUnexpected); cout << "Code before exception handling" << endl; try { foo2(3); // throw MyStructException cout << "Will not be printed"; } catch (int ex) { cout << "Integer exception: " << ex << endl; } catch (MyStructException& ex) { cout << "Struct exception : " << ex.reason; } cout << "Continuing after block with EH"; // We may reset unexpected handler to default std::set_unexpected(std::terminate); return 0; }

47 PB161 Vhodnost použití – opakovaná obsluha chyb Výjimky mohou výrazně omezit podmíněný kód pro obsluhu chyby ●kód s podmínkami obsahuje nejčastěji chybu ●výjimky omezují množství kódu s podmínkami ●musí však být používány správně (viz. zneužívání) Při použití výjimek nemusíme mít kód pro vyhodnocení a předání chyby v každé funkci STL algs, Výjimky, Functor

48 PB161 Vhodnost použití výjimek - konstruktory Chybu v konstruktoru nelze předat návratovou hodnotou ●žádná není ●typicky chybné argumenty Lze řešit nějakou validační metodou “isValid()” ●může být nepohodlné ●musíme testovat každý vytvářený objekt Při chybě v konstruktoru lze vyhodit výjimku ●viz. prázdné jméno u třídy Person ●typicky instance std::invalid_argument nebo její potomek ● throw std::invalid_argument(“Invalid empty name”); STL algs, Výjimky, Functor

49 PB161 Vhodnost použití výjimek - operátory Chyby při použití operátorů ●operátory typicky nevrací chybový status ●návratová hodnota operátoru nemusí být použitelná ●např. operátor sčítání může způsobit přetečení výsledku Některé operátory nastavují “fail” bit ●např. >> a << pro iostream ●může být nutné testovat po každé operaci - nepraktické Při chybě v operátoru lze vyhodit výjimku ●např. při detekci přetečení u sčítání ● throw std::overflow_error(“+ result overflow”); STL algs, Výjimky, Functor

50 PB161 Výjimky pro I/O operátory STL algs, Výjimky, Functor #include int main() { std::cin.exceptions( std::istream::failbit); try { int i; std::cin >> i; std::cout << "Succesfully read: " << i << std::endl; } catch (std::istream::failure & ex) { std::cout << "Exception: " << e.what() << std::endl; } return 0; } int x; cin >> x; if (cin.fail()) { }

51 PB161 (Ne)vhodnost použití výjimek – dealokace Výjimka může způsobit memory leak ●kód s dealokací díky výjimce neproběhne Lze řešit kombinací zachycení a znovuvypuštění ● catch (…) { delete[] data; throw; } Lze řešit použitím auto_ptr,unique_ptr ●vhodnější, můžeme deklarovat i alokovat v podblocích STL algs, Výjimky, Functor

52 PB161 Zneužívání a nadužívání výjimek STL algs, Výjimky, Functor Zachytávání, ale neošetřování výjimek ● catch (…) { /* do nothing */ } ●zachytíme vše a nereagujeme Nadužívání výjimek ●např. nadměrné testování přístupu k poli pomocí at() 52 std::vector myVect(100, 5); float result = 0; for (unsigned int i = 0; i < ; i++) { if (i < myVect.size()) result += myVect[i]; } for (unsigned int i = 0; i < ; i++) { try { result += myVect.at(i); } catch (std::out_of_range& ex) { // do nothing } bez výjimky s výjimkou

53 PB161 Problém s defaultním destruktorem Může nastat při vytváření vlastní výjimky jako potomek exception ●error: looser throw specifier for … ●pozor, ne všechny překladače hlásí Nastává, pokud u třídy výjimky definujeme atributy s vlastním destruktorem ●např. std::string pro uložení dalších informací ●atribut může způsobit vyvolání výjimky, kterou předek v throw deklaraci nespecifikuje Více viz. throw-specifier throw-specifier STL algs, Výjimky, Functor

54 PB161 Další informace k výjimkám Motivace a pravidla pro vhodnost použití výjimek ●http://www.parashift.com/c++-faq-lite/exceptions.htmlhttp://www.parashift.com/c++-faq-lite/exceptions.html Princip výjimek a vhodnost (např. RAII) ●http://www.gamedev.net/reference/articles/article953.a sphttp://www.gamedev.net/reference/articles/article953.a sp STL algs, Výjimky, Functor

55 PB161 Standardní výjimky bad_alloc – při dynamické alokaci (typicky nedostatek paměti) bad_cast – chybné přetypování bad_exception – vyvolaná výjimka není v seznamu deklarovaných výjimek bad_typeid – výjimka vyvolaná funkcí typeid ios_base::failure – problém STL algs, Výjimky, Functor

56 PB161 Výjimky - ukázky exceptionTypeDemo.cpp ●zachycení výjimek různých typů exceptionDemo.cpp ●zachycení obecnější výjimky před specifičtější (chyba) exceptionReThrowDemo.cpp ●ukázka znovuvyvolání výjimky unhandledException.cpp ●ukázka neošetřené výjimky exceptionSpeedDemo.cpp ●ukázka nadužívání výjimek exceptionSpecifDemo.cpp ●ukázka použití specifikace vyvolávaných výjimek STL algs, Výjimky, Functor

57 PB161 Shrnutí STL Algoritmy ●Velké množství předpřipravených operací nad kontejnery a itearátory Functor ●Objekt využitelný namísto funkčního ukazatele Výjimky jsou nástroj pro usnadnění ošetření chyb ●Společné místo pro ošetření výjimek z většího rozsahu kódu ●Lze využít dědičnosti ●Pozor na nadužívání výjimek STL algs, Výjimky, Functor

58 PB161 Bonus STL algs, Výjimky, Functor


Stáhnout ppt "PB161 PB161 – Programování v jazyce C++ Objektově Orientované Programování STL algoritmy, Funktory, Výjimky STL algs, Výjimky, Functor 3.11.2014 1."

Podobné prezentace


Reklamy Google