PB161 – Programování v jazyce C++ Objektově Orientované Programování

Slides:



Advertisements
Podobné prezentace
Pro začátek něco lehčího
Advertisements

ÚVOD DO C++ 3 TŘÍDY a objekty - POKRAČOVÁNÍ
Tomáš Petříček Microsoft C# MVP
Přednáška 11 Jiří Šebesta
LOV, Listbox, Poplist a Combobox v Oracle Forms LOV – seznam hodnot, které se zobrazí po stisku klávesy Enter v textovém poli. LOV – seznam hodnot, které.
C++ Přednáška 1 Neobjektové rozšíření jazyka Základy vstupu a výstupu Ing. Jiří Kulhánek, kat. 352, VŠB TU Ostrava 2004.
Vnitřní řazení v poli (in sito)
Třída Array Je součásti balíčku java.util Účelem je usnadnit práci s poli Metody – nejpoužívanější equel(),fill(),sort() a binarySearch() equels() Slouží.
Pole, ukazatele a odkazy
BLIŽŠÍ POHLED NA TŘÍDY, DĚDIČNOST - úvod
Algoritmy I Cvičení č. 1.
Programování v C++ cvičení Filip Zavoral.
Databázové systémy II Přednáška č. 6 RNDr. David Žák, Ph.D. Fakulta elektrotechniky a informatiky
Genetické algoritmy [GA]
Programování v C++ Cvičení.
PROGRAMOVACÍ JAZYKY (c) Tralvex Yeap. All Rights Reserved.
C++0x stručný náhled na nadcházející revizi standardu programovacího jazyka C++ (ISO/IEC 14882) Jan Ringoš.
Medians and Order Statistics Nechť A je množina obsahující n různých prvků: Definice: Statistika i-tého řádu je i-tý nejmenší prvek, tj., minimum = statistika.
Metody řazení s lineární časovou složitostí
1 Vyhledávání Principy vyhledávání Klasifikace klíče:  Interní klíč – je součástí prohlížených záznamů  Externí klíč – není jeho součástí, je jím např.
C# - datové typy Centrum pro virtuální a moderní metody a formy vzdělávání na Obchodní akademii T.G. Masaryka, Kostelec nad Orlicí.
OSNOVA: a) Řetězce v C b) Funkce stdio.h pro řetězce c) Funkce string.h pro řetězce d) Příklad Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače.
PB161 Jmenné prostory, I/O proudy PB161 | Jmenné prostory, IO proudy PB161 – Programování v jazyce C++ Objektově Orientované Programování.
Seminář C cvičení STL, Trolltech Ing. Jan Mikulka.
Algoritmy a programovací techniky
Vaše první aplikace V rámci projektu „Cesta k vědě“ (veda.gymjs.net) vytvořil V. Pospíšil a Antonín Šulc. Modifikace a.
Dynamická alokace, polymorfismus
PB161 – Programování v jazyce C++ Objektově Orientované Programování
 termín: středa :59  vytvořit kontejner – dvourozměrná matice  dopředné (forward) iterátory přes sloupce i řádky  velikost fixní, určená parametry.
Algoritmizace a programování Třídící algoritmy - 12
PB161 Právo friend, přetěžování operátorů, přetypování PB161 | Friend, operátory PB161 – Programování v jazyce C++ Objektově Orientované Programování.
Memento. Obnovení operačního systému ( Windows | Linux...) Všichni víme, co jsou transekce v databázi Memento – zálohování databáze.
OSNOVA: a)Programování se soubory b)Záloha databáze v souboru c) Příklady Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování.
PB161 PB161 – Programování v jazyce C++ Objektově Orientované Programování Šablony, Návrhové principy a (anti-)vzory PB161 | Šablony, Návrhové principy.
OSNOVA: a) Úvod do OOPb) Třídy bez metod c) Třídy s metodamid) Konstruktory a destruktory e) Metody constf) Knihovní třídy g) Třídy ve tříděh) Přetížení.
A1PRG - Programování – Seminář Ing. Michal Standardní knihovní funkce pro vstup a výstup 12 Verze
C# - předávání parametrů Centrum pro virtuální a moderní metody a formy vzdělávání na Obchodní akademii T.G. Masaryka, Kostelec nad Orlicí.
Pokročilé programování v C++ (část B) David Bednárek
OSNOVA: a) Přetížení členských funkcí b) Dědičnost tříd Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 2 pro obor EST BPC2E.
Příklady v jazyku C – část 2
0 / 1X36DSA 2005The complexity of different algorithms varies: O(n), Ω(n 2 ), Θ(n·log 2 (n)), … Různé algoritmy mají různou složitost: O(n), Ω(n 2 ), Θ(n·log.
Metodika objektového přístupu při tvorbě překladačů. Marek Běhálek Informatika a aplikovaná matematika FEI VŠB-TU Ostrava.
KIV/PPA1 cvičení 9 Cvičící: Pavel Bžoch. Osnova cvičení Třída String a její metody –Řetězce a operace s nimi.
Dynamic SQL P. Částek. Dynamic SQL Embedded SQL je překládaný preprocesorem => za běhu nelze nechat uživatele rozhodovat o vzhledu samotných SQL příkazů.
STRING A UKAZATELE. Co to je řetězec? Řetězec v Javě je samostatný objekt. Je konstantní, co znamená, že jednou vytvořený řetězec nelze změnit. Chceme-li.
OSNOVA: a) Algoritmy třídění b) Třídění dynamických záznamů Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 1 pro obor EST.
Pokročilé programování v C++ (část B)
Ukazatele, řetězce Přednáška č. 3. Ukazatele  Ukazatel (pointer) – typ o velikosti 4 bajty (v 32bit. systémech) pro uložení adresy objektu na který ukazuje.
Pythia8 Jiří Chudoba, na základě práce a prezentací Torbjerna Sjostranda.
Příklady v jazyku C – část 2
David Bednárek Programování v C++ David Bednárek
Strategy. Motivace Různé algoritmy pro stejnou akci Hromada kódu v mnoha podmínkách Důsledky  Komplexnost  Špatná čitelnost  Těžká správa kódu  Těžka.
Jazyk C++ Přednáška č.2 Proudy, manipulátory Práce se soubory
Šablony funkcí a tříd Šablony v C++ jsou vzory, podle kterých může překladač vytvářet celé skupiny podobných tříd či funkcí, které se liší jen v některých.
PROGRAMOVÁNÍ 3ITA,3ITB Jaroslav Burdys Hlavní zdroj:
Programování OPERÁTOR SIZEOF, FUNKCE, POLE JAKO PARAMETRY FUNKCÍ ERIK KRÁL.
Počítače a programování 2
Y36PJC Programování v jazyce C/C++
Standard Template Library - „Knihovna standardních šablon“
Y36PJC Programování v jazyce C/C++
Ruby on Rails framework vývoj aplikací pro WWW
Počítače a programování 2 pro obor EST BPC2E PŘEDNÁŠKA 3
Databázové systémy a SQL
ALG 07 Selection sort (Select sort) Insertion sort (Insert sort)
Různé algoritmy mají různou složitost
ALG 09 Radix sort (přihrádkové řazení) Counting sort
Přednášky z distribuovaných systémů
C# přehled vlastností.
Přednáška 9 Triggery.
ALG 14 Vícedimenzionální data Řazení vícedimenzionálních dat
Transkript prezentace:

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

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

STL Algoritmy STL algs, Výjimky, Functor 3.11.2014

STL zavádí nové koncepty 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) 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. Algoritmy běžné operace vykonané nad celými kontejnery např. sort(str.begin(), str.end()) 6. Přednáška STL algs, Výjimky, Functor 3.11.2014

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 // sort algorithm example from http://www.cplusplus.com/reference/algorithm/sort/ #include <algorithm> #include <vector> using namespace std; int main () { vector<int> myvector; // fill vector by values sort (myvector.begin(), myvector.end()); return 0; } STL algs, Výjimky, Functor 3.11.2014

Algoritmy - dokumentace Funkce dostupné v <algorithm> http://www.cplusplus.com/reference/algorithm/ Ukázka syntaxe na for_each STL algs, Výjimky, Functor 3.11.2014

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 http://www.cplusplus.com/reference/algorithm/ STL algs, Výjimky, Functor 3.11.2014

http://www.cplusplus.com/reference/algorithm Převzato z STL algs, Výjimky, Functor 3.11.2014

http://www.cplusplus.com/reference/algorithm Převzato z STL algs, Výjimky, Functor 3.11.2014

STL algoritmy – find #include <iostream> #include <list> #include <iterator> #include <algorithm> using std::cout; using std::endl; int main() { std::list<int> 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<int>::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()) { else cout << "10 not found" << endl; return 0; STL algs, Výjimky, Functor 3.11.2014

STL algoritmy – for_each a transform #include <iostream> #include <list> #include <algorithm> using std::cout; using std::endl; int increase10(int value) { return value + 10; } void print(int value) { cout << value << endl; 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 int main() { std::list<int> 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; } STL algs, Výjimky, Functor 3.11.2014

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) std::for_each(myList.begin(), myList.end(), print); template<class InputIterator, class Function> Function for_each(InputIterator first, InputIterator last, Function f) { for ( ; first!=last; ++first ) f(*first); return f; } STL algs, Výjimky, Functor 3.11.2014

STL algoritmy – sort #include <iostream> // sort algorithm example from http://www.cplusplus.com/reference/algorithm/sort/ #include <iostream> #include <algorithm> #include <vector> using namespace std; bool myfunction (int i,int j) { return (i<j); } int main () { int myints[] = {32,71,12,45,26,80,53,33}; vector<int> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33 vector<int>::iterator it; // using default comparison (operator <): sort (myvector.begin(), myvector.begin()+4); //(12 32 45 71)26 80 53 33 // using function as comp sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80) cout << endl; return 0; } STL algs, Výjimky, Functor 3.11.2014

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

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 3.11.2014

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 3.11.2014

Nyní přičítač stojedničky #include <iostream> #include <list> #include <algorithm> 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; } }; Functor - ukázka int main() { std::list<int> 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); return 0; } Nyní přičítač trojky Nyní přičítač stojedničky STL algs, Výjimky, Functor 3.11.2014

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 3.11.2014

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 3.11.2014

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

Přetížíme operátor () pro aplikaci unární funkce class UnaryFunction { public: virtual ~UnaryFunction() {} virtual int operator() (int arg) const = 0; }; class UnaryNumericFunction : public UnaryFunction { 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 { Adder(int r) : UnaryNumericFunction(r) {} int operator() (int arg) const { return arg + rightOperand(); } class Multiplier : public UnaryNumericFunction { 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 Parametrizace functoru V přetiženém operátoru () přičítáme STL algs, Výjimky, Functor 3.11.2014

Parametrizace functoru probíhá přidáváním unárních funkcí // 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<UnaryFunction*>::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<UnaryFunction*> 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 STL algs, Výjimky, Functor 3.11.2014

Použití functorů #include <iostream> Vytváříme functor comp #include <algorithm> #include <list> 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 STL algs, Výjimky, Functor 3.11.2014

Výjimky (Exceptions) STL algs, Výjimky, Functor 3.11.2014

Obsluha chyby – bez výjimek Proměnná s hodnotou chyby (0 == OK) 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; // ... do something else if (status != 0) { // Some problem? // ... report problem, roll back info.... return status; Test, zda se nevyskytla chyba V případě chyby nastav status Každý další logický blok kódu obalen testem na OK Udělej něco v reakci na problém Vrať informaci o průběhu STL algs, Výjimky, Functor 3.11.2014

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 3.11.2014

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 try { // … some code throw std::logic_error("Problem"); // … some code (not executed) } catch (std::logic_error& ex) { // … handle somehow exception cout << ex.what() << endl; STL algs, Výjimky, Functor 3.11.2014

Výjimky (Exception) - princip 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) Výjimka postupně “stoupá” volajícími funkcemi (callstack), dokud ji někdo nezachytí Výjimka je zachycena obslužným blokem specifikuje, v jaké části kódu a jaké výjimky zachytávat try/catch blok 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 3.11.2014

Ukázka 1. Výjimka vyvolána Kód nebude vykonán 2. Výjimka zachycena, 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; } }; 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; 1. Výjimka vyvolána Kód nebude vykonán 2. Výjimka zachycena, obsloužena a zaniká 3. Program pokračuje STL algs, Výjimky, Functor 3.11.2014

Datový typ výjimky Primitivní datové typy Struktury, třídy 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 3.11.2014

Vyhazuje různé typy výjimek podle what #include <iostream> #include <stdexcept> #include <string> 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"); 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; foo(1) foo(2) Vyhazuje různé typy výjimek podle what foo(3) foo(4) STL algs, Výjimky, Functor 3.11.2014

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 <stdexcept> 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/ STL algs, Výjimky, Functor 3.11.2014

new a zachycení výjimky class A { int m_value; public: A(int value) : m_value(value) {} void print() const {cout << m_value << endl; } }; // 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"; STL algs, Výjimky, Functor 3.11.2014

Vlastní výjimky - třídy 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 http://www.cplusplus.com/reference/std/stdexcept/ STL algs, Výjimky, Functor 3.11.2014

Vlastní výjimky - ukázka Výjimka může nést dodatečné informace dle našich potřeb Jméno výjimky rodič výjimky zvolte co nejspecifičtěji 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 () {} }; Můžeme přidat vlastní dodatečné metody Konstruktor pro specifikace informací o výjimce. Inicializuje i předka. Destruktor – nutné pokud máme atributy, které mají také destruktor STL algs, Výjimky, Functor 3.11.2014

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 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 STL algs, Výjimky, Functor 3.11.2014

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 3.11.2014

Pořadí zachycení – ukázka problému 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 STL algs, Výjimky, Functor 3.11.2014

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 3.11.2014

Znovuposlání výjimky - ukázka 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 Prázdné jméno způsobí výjimku Výjimka odchycena, ale poslána dál int main() { try { foo(); } catch (std::logic_error& ex) { cout << "Exception std::logic_error : " << ex.what(); return 0; Výjimka znovu zachycena a finálně zpracována. STL algs, Výjimky, Functor 3.11.2014

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 3.11.2014

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 3.11.2014

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

Nezachycená výjimka Může nastat když Následuje ukončení programu neobsluhujeme výjimky vůbec nastane mimo blok s obsluhou výjimky Následuje ukončení programu #include <stdexcept> 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; } STL algs, Výjimky, Functor 3.11.2014

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 http://www.gotw.ca/publications/mill22.htm vývojáře nekontroluje (až za běhu), překladači téměř nepomáhá STL algs, Výjimky, Functor 3.11.2014

Seznam vyvolávaných výjimek - ukázka 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 <iostream> #include <stdexcept> #include <string> 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; STL algs, Výjimky, Functor 3.11.2014

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 3.11.2014

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 3.11.2014

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 3.11.2014

Výjimky pro I/O operátory int x; cin >> x; if (cin.fail()) { } #include <iostream> 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; STL algs, Výjimky, Functor 3.11.2014

(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 3.11.2014

Zneužívání a nadužívání výjimek 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() std::vector<int> myVect(100, 5); float result = 0; for (unsigned int i = 0; i < 10000000; i++) { if (i < myVect.size()) result += myVect[i]; } try { result += myVect.at(i); catch (std::out_of_range& ex) { // do nothing bez výjimky s výjimkou STL algs, Výjimky, Functor 3.11.2014

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. http://www.agapow.net/programming/cpp/looser-throw-specifier STL algs, Výjimky, Functor 3.11.2014

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

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 3.11.2014

Výjimky - ukázky Ukázky exceptionTypeDemo.cpp exceptionDemo.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 3.11.2014

Shrnutí STL Algoritmy Functor 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 3.11.2014

Bonus  STL algs, Výjimky, Functor 3.11.2014