Objektově orientované programování

Slides:



Advertisements
Podobné prezentace
A1PRG - Programování – Seminář Ing. Michal Typová konverze, oblast platnosti, paměťové třídy 9 Verze
Advertisements

Standardní knihovní funkce pro práci s textovými řetězci
(instance konkrétní třídy)
Seminář C++ 5. cvičení Dědičnost Ing. Jan Mikulka.
Programovací jazyk C++
Programování 2 Cvičení 5.
Úvod do objektově orientovaného programování
Pole, ukazatele a odkazy
ÚVOD DO CPP 7 Dědičnost - pokračování
BLIŽŠÍ POHLED NA TŘÍDY, DĚDIČNOST - úvod
PJV151 Vnořené a vnitřní členy mohou být členy tříd a interfejsů. Je-li X obalem Y a Y je obalem Z, pak Z získá jméno X$Y$Z - kompilací vzniknou classy.
Programování v C++ Cvičení.
Principy překladačů Běhová podpora Jakub Yaghob. Běhová podpora Statická podpora jazyka Překladač Interface na knihovny Hlavičkové soubory Dynamická podpora.
Programování 02 OOP.
Čtvrté cvičení Objektové programování Objektový model v Javě
Programování v Pascalu Přednáška 7
C++0x stručný náhled na nadcházející revizi standardu programovacího jazyka C++ (ISO/IEC 14882) Jan Ringoš.
Materiály k přednášce Úvod do programování Ondřej Čepek.
J a v a Začínáme programovat Lucie Žoltá metody, objekty, konstruktor.
Objekty v CLIPSu RNDr. Jiří Dvořák, CSc.
C# - struktury, výčtové typy, pole
State. State – kontext a problém Kontext  chování objektu má záviset na jeho stavu, který se typicky mění za běhu Neflexibilní řešení  metody obsahují.
Páté cvičení Dědičnost Interface Abstarktní třídy a metody
Vyučovací hodina 1 vyučovací hodina: Opakování z minulé hodiny 5 min Nová látka 20 min Procvičení nové látky 15 min Shrnutí 5 min 2 vyučovací hodiny: Opakování.
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.
PB161 – Programování v jazyce C++ Objektově Orientované Programování
Objektové programování
Dynamická alokace, polymorfismus
Seminář C cvičení Obsluha výjimek Ing. Jan Mikulka.
Současný svět Projekt č. CZ /3. 1
PB161 – Programování v jazyce C++ Objektově Orientované Programování
6. cvičení Polymorfismus
A1PRG - Programování – Seminář Ing. Michal Ukazatele a pole 10 Verze
Počítače a programování 1
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í.
KIV/PPA1 cvičení 8 Cvičící: Pavel Bžoch. Osnova cvičení Objekty v Javě Třída Konstruktor Metody Metody a proměnné třídy x instance Program sestávající.
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í.
Algoritmizace a programování Objektově orientované programování - 16 Mgr. Josef Nožička IKT Algoritmizace a programování
PB161 Principy OOP - rozhraní, dědičnost PB161 | Principy OOP - Dědičnost, rozhraní
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í.
IB111 Programování a algoritmizace
Návrh a tvorba WWW Přednáška 5 Úvod do jazyka PHP.
Dědičnost - inheritance dědičnost je jednou z forem znovupoužitelnosti dědičnost je jednou z forem znovupoužitelnosti B A Třída A je předkem třídy B Třída.
7. Typ soubor Souborem dat běžně rozumíme uspořádanou množinu dat, uloženou mimo operační paměť počítače (na disku). Pascalský soubor je abstrakcí skutečného.
13/04/20151 Indexery (1) Členy třídy (struktury) umožňující třídě (struk- tuře) používat hranaté závorky a pracovat s ní podobně jako s polem (používat.
13/04/20151 Datový typ třída – class (1) Datový typ definovaný uživatelem Poskytuje mechanismus pro modelování entit, s nimiž manipulují aplikace Charakterizuje.
Šesté cvičení Výjimky Balíky.
Principy OOP Objektově orientované programování vychá-zí ze třech základních principů (rysů): zapouzdření (encapsulation) dědičnost (inheritance) polymorfismus.
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.
Počítače a programování 1 7.přednáška. Základy Pole ve třídách a metodách Pole Arrays.
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.
Soubory BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky © Miroslav Balík Fakulta informačních technologií České vysoké.
Jazyk C A0B36PRI - PROGRAMOVÁNÍ Část II.
C – procedury Mgr. Lenka Švancarová.
Podprogramy (subroutines) Pojmenované kousky programu, které –tvoří logicky ucelené části –se v programu opakují Jsou zapsány na jednom místě a v případě.
IB111 Práce se soubory Správa paměti. Práce se soubory v Pythonu Soubor musíme „otevřít“ Poté s ním pracujeme –Čteme a/nebo zapisujeme Nakonec musíme.
Programování v jazyce C++ Dědičnost a polymorfismus.
Programování OPERÁTOR SIZEOF, FUNKCE, POLE JAKO PARAMETRY FUNKCÍ ERIK KRÁL.
Programování v jazyce C++ Speciality jazyka C++, úvod do OOP.
Y36PJC Programování v jazyce C/C++
Úvod do C# - OOP Jaroslav BURDYS 4IT.
Programování ENUM, SWITCH,pole jednorozměrná a vícerozměrná, deklarace, inicializace, kopírování, porovnání Erik Král.
Y36PJC Programování v jazyce C/C++
Programování v jazyce C++
Programování 2. hodina RNDr. Jan Lánský, Ph.D.
Programování v jazyce C++
Bridge.
C# přehled vlastností.
Transkript prezentace:

Objektově orientované programování RNDr. Jan Lánský, Ph.D. Katedra softwarového inženýrství MFF UK Katedra informatiky VŠFS (Autor původní verze slajdů: Mgr. Zbyněk Winkler) (Autor prapůvodní verze slajdů: RNDr. Filip Zavoral, Ph.D.) (Část slajdů převzata od: RNDr. David Bednárek) zizelevak@gmail.com http://kocour.ms.mff.cuni.cz/~lansky/

Zápočet Zdrojové kódy v minimálním rozsahu 1500 řádků, doporučeno 2500 řádků. Nejlépe: Vlastní ucelený příklad, který něco rozumného dělá Vlastní jednoduché příklady, zadání může být z knihy Nejhůře: Příklady probírané na cvičení PS: Aktivní účast na cvičeních (8 účastí z 12 možných) KS: Aktivní účast na soustředěních, 4 účasti z 9 možných) Chybějící účast (pod stanovený limit) lze nahradit: PS: +200 řádků zdrojových kódů za 1 hodinu neúčasti KS: +400 řádků zdrojových kódů za 1 neúčast na soustředění. Pozor v jeden den bývají obvykle 2 až 3 soustředění) Příklad: PS student X se zúčastnil jedné hodiny cvičení. Na zápočet odevzdá 1500 + (8 – 1)*200 = 2900 řádků zdrojových kódů. Příklad: KS student Y se zúčastnil pouze výuky 1.4.2015 kdy proběhly 2 hodiny soustředění. Na zápočet odevzdá 1500 + (4 – 2)*400 = 2300 řádků zdrojového kódu.

Diskuze nad zdrojovými kódy předloženými k získání zápočtu. Zkouška Diskuze nad zdrojovými kódy předloženými k získání zápočtu. Zkušební okruhy Reference jako parametr funkce a návratová hodnota Přetěžování funkcí a operátorů, new a delete Bezparametrický konstruktor, copy konstruktor, operator =, destruktor Dědičnost, Virtuální funkce, abstraktní třídy Prostory jmen Streamy, práce se soubory Šablony funkcí a tříd STL kontejnery, iterátory a algoritmy Výjimky

Literatura Miroslav Virius: Programování v C++ Miroslav Virius: Pasti a propasti jazyka C++ Miroslav Virius: Od C k C++ Scott Meyers: Effective C++, More Effective C++, Effective STL Herb Sutter: Exceptional C++, More Exceptional C++ Que: ANSI/ISO C++ Professional Programmer's Handbook Bruce Eckel: Myslíme v jazyce C++ James O. Coplien: Advanced C++ Programming Styles and Idioms Bjarne Stroustrup: The C++ Programming Language ISO/IEC 14882, ANSI: Programming languages - C++ (1998, 2003) Stroustrup 3rd ed

Obsah předmětu C C ZS (PJC) LS (OOP) C++ C++ Paradigmata programování, OOP Objekty, zapouzdření, dědičnost, konstruktory a destruktory Přetěžování funkcí, předefinování operátorů Pozdní vazba, virtuální funkce Abstraktní datové typy Šablony, výjimky, prostory jmen. Objektové knihovny: streams, STL RTTI, OO styly a idiomy...

Paradigmata programování Procedurální programování jakou akci mám provést vstup – výpočet (algoritmus) – výstup black box: procedura / funkce Modulární programování rozdělení problému na komponenty procedury pracují nad daty - rozhraní black box: modul Datová abstrakce vytvoření vlastního datového typu (abstract/user defined datové typy) kompletní množina operací nad tímto typem black box: datový typ Objektové programování dědičnost – obecné / konkrétní vlastnosti Polymorfismus – odlišné chování potomků možnost pozdějších rozšíření zapouzdření side effects, údržba nelze rozumně rozšiřovat dále – generické programování šablony, STL

Třídy a objekty Koncepční pohled Technický pohled objekt: entita reagující na vnější podněty třída: množina stejně reagujících entit Technický pohled objekt: struktura obsahující data a funkce, instance třídy (proměnná) třída: typ objektu – jednotná struktura dat, stejné operace nad daty Zobecnění pojmu struktura (struct) Rozdíl mezi class a struct v C++ je nepatrný, užívání class je pouze konvence deklarace třídy obsahuje Deklarace datových položek (stejně jako v C) Funkce (metody), virtuální funkce a statické funkce Definice výčtových konstant a typů (včetně vnořených tříd) Rozhraní – veřejné informace a služby pro uživatele Implementace – (neveřejná) interní data a metody (funkce)

Třída zvíře v C++ - rozhraní zvire.h definice třídy rozhraní (veřejné) class Zvire { private: int zaludek; public: Zvire() { zaludek = 1; }; int zije() { return zaludek>0; }; int jez( int jidlo); int vymesuj( int objem); }; vnitřní stav (privátní) Datová položka konstruktor (inicializace) inline tělo funkce metody Deklarace metody

Třída zvíře - implementace zvire.h zvire.cpp class Zvire { private: int zaludek; public: Zvire() { ... }; int zije() { ... }; int jez( int jidlo); int vymesuj( int objem); }; :: operátor kvalifikace Třída metody #include ”zvire.h” int Zvire::jez( int jidlo) { if( ! zije()) return 0; return zaludek += jidlo; } int Zvire::vymesuj( int objem) if( (zaludek -= objem) <= 0) zaludek = 0; return zaludek; Implementace (tělo) metody Přístup k datům metody Středník !!!

Třída zvíře - použití mujprogram.cpp zvire.h Import rozhraní class Zvire { private: int zaludek; public: Zvire() { ... }; int zije() { ... }; int jez( int jidlo); int vymesuj( int objem); }; #include ”zvire.h” ..... { Zvire pytlik; pytlik.jez(5); pytlik.vymesuj(3); if( ! pytlik.zije()) return -1; pytlik.vymesuj(4); if( ! pytlik.jez(1)) return -2; } Automatický konstruktor zaludek = 1 Instance třídy = objekt zaludek = 6 zaludek = 3 -1  0 

Objekt - instance třídy int Zvire::jez( int jidlo) { if( ! zije()) return 0; return zaludek += jidlo; } ..... Zvire pytlik, beruska; pytlik.jez( 5); beruska.jez( 1); Metoda třídy - ke kterému objektu má přistupovat? ? pytlik: 6 zaludek dvě instance třídy beruska: 2 zaludek

this C C++ this pytlik: beruska: Každá metoda dostane 'tajný' parametr this – ukazatel na objekt zvire:: znamena zvire * this C C++ int jez( Zvire* this, int jidlo) { if( ! zije( this)) return 0; return this->zaludek += jidlo; } ..... Zvire pytlik, beruska; jez( &pytlik, 5); jez( &beruska, 1); int Zvire::jez( int jidlo) { if( ! zije()) return 0; return zaludek += jidlo; } ..... Zvire pytlik, beruska; pytlik.jez( 5); beruska.jez( 1); this->zije() this->zaludek this pytlik: 6 zaludek beruska: 2 zaludek

Reference x: 3 :px y: 4 :ry x: 1 :a y: 2 :b reference pouze inicializace nelze měnit int x = 1, y = 2; int *px; px = &x; *px = 3; int &ry = y; ry = 4; return *px + ry; x: 3 :px y: 4 :ry reference i ukazatele jsou reprezentovány adresou swap( int& a, int& b) { int c = a; a = b; b = c; } int x = 1, y = 2; swap( x, y); skutečné parametry odkazy na proměnné x: 1 :a y: 2 :b zpřehlednění kódu přetěžování funkcí

Přetěžování funkcí Funkce je definována svým identifikátorem a počtem a typem parametrů int pocitej( int x) { return x+1; } int pocitej( int a, int b) return 2*a + b; int pocitej( int a, const char* s) return a + strlen( s); pocitej( 1); // int pocitej( int) pocitej( 1, 2); // int pocitej( int, int) pocitej( 1, "ahoj"); // int pocitej( int, char*) Funkce se stejným identifikátorem ale různým počtem parametrů Funkce se stejným počtem ale různým typem parametrů Správná funkce podle počtu a typů skutečných parametrů

Volá se stále stejná funkce int fce( int, int, int) Implicitní parametry Některé parametry funkce mohou mít implicitní hodnoty pokud nejsou všechny parametry implicitní – implicitní parametry odzadu Při volání funkce lze implicitní parametry vynechat použije se implicitní hodnota Kdy použít přetěžování a kdy implicitní parametry? Stejný kód pro různý počet parametrů implicitní parametry Pro různé počty nebo typy parametrů různý kód přetěžování int fce( int a, int b = 2, int c = 4) { return 2*a + b - c; } fce( 1); // int fce( 1, 2, 4) fce( 1, 5); // int fce( 1, 5, 4) fce( 1, 5, 6); // int fce( 1, 5, 6) Volá se stále stejná funkce int fce( int, int, int)

Konstruktory class Zvire { private: int zaludek; public: Implicitní konstruktor bez parametrů class Zvire { private: int zaludek; public: Zvire() { zaludek = 1; }; Zvire( int zal) { zaludek = zal; }; Zvire( const Zvire& vzor) { zaludek = vzor.zaludek; }; }; Zvire beruska; Zvire pytlik( 20); Zvire beberuska( beruska); Zvire tlustoch = pytlik; Konstruktor s parametry Copy konstruktor X (const X&) vytvoří objekt jako kopii jiného různé zápisy copy konstruktoru Pro U≠T nejsou zcela ekvivalentní: U u; T t(u); // T::T( U&) T t = u; // T::T( T(u)) nebo // T::T( u.operator T()) zatím lze ignorovat

Konstruktor s parametry Tímto zakážeme deklarovat objekt bez použití NEimplicitního konstruktoru class Clovek { private: char jmeno[50]; Clovek(); public: //Clovek() { jmeno[0] = 0; }; Clovek( char * jmeno) { strcpy(this->jmeno, jmeno); }; Clovek honza("Honza"); //Clovek petr; Využití Předání nastavení objektu Šetří řádky kódu Zakázat implicitiní konstruktor Dobře rozvážit zda zakázat Bezpečnost proti nezadání klíčové hodnoty identifikátor Nejde, zakázali jsme

Přetěžování operátorů - deklarace implicitní parametry  implicitní konstruktor class Bod { private: int x, y; public: Bod( int xx=0, int yy=0) { x=xx; y=yy; }; Bod operator+( const Bod&); Bod operator=( const Bod&); }; Bod a(1,2), b, c; c = a + b; přetížení operátoru + a + b  a.operator+(b) a = b  a.operator=(b) Bod::Bod(0,0); c.operator=(a.operator+(b)); c.assign( a.add( b));

Přetěžování operátorů – těla metod Bod Bod::operator=( const Bod& b) { x = b.x; y = b.y; return *this; } Bod Bod::operator+( const Bod& b) return Bod( x+b.x, y+b.y); reference x  this->x aktualizace stavu kopie objektu (hodnotou přiřazení je přiřazovaná hodnota) vytvoření dočasného objektu konstruktor Bod::Bod(int, int) co to je ???

Přetěžování operátorů - pravidla Většinu operátorů jazyka C++ lze definovat pro uživatelské datové typy Nelze předefinovat tyto operátory: .  .*  ::   ? :  sizeof Alespoň jeden z operandů musí být třída nebo výčtový typ nebo reference na ně Nelze předefinovat operace na číselných typech a ukazatelích Předefinováním nelze měnit prioritu a asociativitu operátorů Pro předefinované operátory nemusí platit identity definované pro základní typy ++a nemusí být ekvivalentní a=a+1 a[b] nemusí být ekvivalentní *(a+b) ani b[a] je však velmi doporučeno dodržovat běžnou sémantiku Pro předefinované operátory && a || neplatí pravidla o zkráceném vyhodnocování Typy skutečných operandů nemusejí přesně odpovídat typům formálních parametrů stejná pravidla jako pro přetížené funkce

Přetěžování operátorů – ekvivalence Pozor!   Pro předefinované operátory nemusí platit identity definované pro základní typy: a=a+b  a+=b a[b]  *(a+b) Bod Bod::operator+=( const Bod& b) { x += b.x; y += b.y; return *this; } Bod Bod::operator+=( const Bod& b) { return *this = *this + b; } this->operator=( this->operator+( b))

copy konstruktor a operator= class Bod { private: int x, y; public: Bod( const Bod& b) { x=b.x; y=b.y; }; Bod operator=( const Bod& b) { x=b.x; y=b.y; return *this; }; }; Bod a(1,2); Bod k, m(a), n = a; k = m; není-li copy konstruktor nebo operator= definován, automaticky se vygeneruje copy konstruktor resp. operator= všech složek copy konstruktor definice nového objektu operator= přiřazení do existujícího objektu Rozdíl mezi copy konstruktorem a přiřazením: copy konstruktor se nemusí starat o předchozí stav objektu, přiřazení ano přiřazení vrací (přiřazovanou) hodnotu, copy konstruktor nevrací nic

Udržovatelnost kódu Těla operátorů a konstruktorů volání jiné funkce Public část před private Private položky nejsou zajímavé Datové položky vždy private Funkce Get a Set Těla metod vždy v *.cpp souboru Pro pozdější rozšíření Lépe se hledá kde je implementované Jména tříd ToJeMojeTrida Jména funkcí proměnných mojePrvniFunkce class Bod { public: Bod( const Bod & b) { dosad(b); }; Bod operator=( const Bod & b) { dosad(b); return *this; }; int GetX() {return x; }; int GetY() {return y; }; void SetX(int x) { this->x = x; } void SetY(int y) { this->y = y; } private: int x, y; void dosad( const Bod & b) { x=b.x; y=b.y; }; };

Objekt a ukazatel na objekt C++ odlišuje objekt a ukazatel na něj Rozdíl oproti jiným jazykům Java, JavaScript, PHP, VisualBasic, ... Analogie s chováním stuct v C Ukazatel nelze použít dokud není splněna jedna z možností: Přiřazen existující objekt Reference Dynamicky vytvořen nový objekt Operátor new class Zvire { ..... }; Zvire * pytlik; Zvire beruska; pytlik = &beruska; pytlik = new Zvire; Nevzniká tu žádný objekt vzniká nový objekt

Operátory new a delete new: alokace paměti, zavolání konstruktoru není nutno testovat úspěšnost – mechanismus výjimek delete: zavolání destruktoru, dealokace paměti jako parametr lze i 0 dynamická alokace, implicitní konstruktor náhrada za malloc() Bod a(1,2); Bod *pb = new Bod; *pb = a + a; a = *pb; delete pb; pb = new Bod( a); Bod *pc = new Bod( 3, 5); a = *pb + *pc; delete pc; uvolnění paměti další alokace, explicitní konstruktory alokace pole objektů char* buf = new char[10]; strcpy( buf, “ahoj”); ... delete[] buf; uvolnění paměti - u alokovaných polí nutno []

‘obyčejné‘ zřetězení – nechci se starat o to, kde sebrat místo Chytré řetězce – nápad Práce s řetězci v C + efektivní – nepohodlá a těžkopádná – časté chyby Chtěl bych: přiřazování, zřetězení, automatická alokace místa Str s1 = “ahoj”; Str s2 = “babi”; Str s3; s3 = s1 + ‘ ‘ + s2; s3 += “.”; s3 = (char*) malloc( strlen(s1) + strlen(s2) + 2); strcpy( s3, s1); s3[ strlen(s1)] = ‘ ‘; strcpy( s3 + strlen(s1) + 1, s2); ‘obyčejné‘ zřetězení – nechci se starat o to, kde sebrat místo

Chytré řetězce - třída class Str ukazatel na alokovaná data { private: char* buf; public: Str() { buf = 0; }; Str( const Str& s); Str( const char* s); ~Str() { delete[] buf; }; Str& operator=( const Str& s); Str operator+( const Str& s); int len() const { return buf ? strlen(buf) : 0; }; }; ukazatel na alokovaná data implicitní konstruktor prázdný řetězec destruktor objekt si musí po sobě uklidit delete přežije i 0, nemusím testovat operace s řetězci další metody (délka řetězce) Konstantní funkce, nemodifikuje objekt

Destruktory class Str { private: char* buf; public: Str() { buf = 0; }; Str( const char* s) { buf = new char[ strlen( s) + 1]; strcpy( buf, s); }; ~Str() { delete[] buf; }; }; ukazatel na alokovaná data alokace paměti pro řetězec destruktor - automaticky se volá při zrušení objektu nemá argumenty nic nevrací

Vyvolání destruktoru v kostruktoru s1 se alokuje paměť pro řetězec fce() { Str s1 = “ahoj”; Str* s2 = new Str( “babi”); ..... delete s2; } dynamická alokace sp2 delete zavolá destruktor (a potom uvolní paměť) zde končí život s1 automaticky se vyvolá destruktor

Řetězce – implementace uklidit po předchozím řetězci Str& Str::operator=( const Str& s) { delete[] buf; if( ! s.len()) { buf = 0; } else { buf = new char[ s.len()+1]; strcpy( buf, s.buf); } return *this; Str::Str( const Str& s) { .... prázdný řetězec alokace paměti okopírování znaků přiřazená hodnota – objekt sám reference kvůli efektivitě copy konstruktor – totéž bez delete a return

O něco lepší implementace později si ukážeme ještě lepší – counted pointers class Str { private: char* buf; void copy( const char* s); public: Str() { buf = 0; }; Str( const Str& s) { copy( s.buf); }; Str( const char* s) { copy( s); }; ~Str() { clear(); }; Str& operator=( const Str& s) { clear(); copy( s.buf); return *this; }; Str& operator=( const char* s) { clear(); copy( s); return *this; }; void clear() { delete[] buf; }; }; privátní metoda – alokace a kopírování konstruktory: jen alokace a kopírování přiřazení: i uklizení a návratová hodnota často potřebujeme uklízet !!! buf = 0; nebo private !!!

Implementace kopírování class Str { private: char* buf; void copy( const char* s); public: Str() { buf = 0; }; Str( const Str& s) { copy( s.buf); }; Str( const char* s) { copy( s); }; ~Str() { clear(); }; Str& operator=( const Str& s) { clear(); copy( s.buf); return *this; }; Str& operator=( const char* s) { clear(); copy( s); return *this; }; void clear() { delete[] buf; }; }; předpokládáme prázdný buf zařídí volající metoda - copy je private void Str::copy( const char* s) { if( !s || !*s) { buf = 0; } else { buf = new char[ strlen( s)+1]; if( buf) strcpy( buf, s); } zkontrolovat prázdný řetězec alokace a kopírování Jde clear() přidat do copy() ???

nové hodnoty VŽDY vracet hodnotou Zřetězení Str Str::operator+( const Str& s) { Str newstr; newstr.buf = new char[ len() + s.len() + 1]; strcpy( newstr.buf, buf); strcat( newstr.buf, s.buf); return newstr; } Str Str::operator+( const char* s) newstr.buf = new char[ len() + strlen(s) + 1]; strcat( newstr.buf, s); nový prázdný řetězec místo na znaky první operand druhý operand návratová hodnota nelze návrat reference (lokální dočasný objekt) nové hodnoty VŽDY vracet hodnotou

lze vracet referencí existující hodnota Připojení řetězce když už umíme + a = proč si neudělat += class Str { .... public: Str& operator=( const Str& s); Str& operator=( const char* s); Str operator+( const Str& s); Str operator+( const char* s); Str& operator+=( const Str& s) { *this = *this + s; return *this; }; Str& operator+=( const char* s) { *this = *this + s; return *this; }; }; operator+( Str&) lze vracet referencí existující hodnota operator+( char*)

dodefinovat konstruktor, přiřazení a operace pro další typ Str a jednotlivé znaky class Str { ... public: Str(); Str( const Str&); Str( const char*); Str( char c) { buf = new char[ 2]; buf[0] = c; buf[1] = '\0'; }; Str& operator=( const Str&); Str& operator=( const char*); Str& operator=( char); Str operator+( int); Str operator+=( int); }; dodefinovat konstruktor, přiřazení a operace pro další typ

Výstup později si ukážeme elegantnější řešení - streams neprázdný obsah na stdout class Str { ... public: int print() const { return buf ? printf( "%s", buf) : 0; }; }; Str s1 = "ahoj", s2("babi"), s3; s3 = s1 + ' ' + s2; s3.print(); Str("\n").print(); (s3 += ".\n").print(); ‘normálně’ spojím řetězce s mezerou ... a vytisknu dočasný objekt reference na s3

... and together class Str { private: char* buf; void copy( const char* s); void clear(); public: Str() { buf = 0; }; Str( const Str& s); Str( const char* s); Str( char c); ~Str(); Str& operator=( const Str& s); Str& operator=( const char* s); Str& operator=( char c); Str operator+( const Str& s); Str operator+( const char* s); Str operator+( char c); Str& operator+=( const Str& s); Str& operator+=( const char* s); Str& operator+=( char c); int len() const; int print() const; };

Dědičnost vztah tříd předek-potomek – hierarchie vícenásobná dědičnost přesnější názvosloví: základní (base) / odvozená třída (derived class) vícenásobná dědičnost dvakrát měř, jednou řež, protokoly specializace potomek má/umí něco navíc reusabilita jiné chování bez změny původní třídy Zvíře Pes Pitbul jez, vyměšuj sedni, lehni trhej Člověk uč_se

pes jako potomek zvířete - definice (odvozená třída od) Zvířete class Zvire { protected: int zaludek; public: Zvire(); Zvire( int jidlo); int zije(); int jez( int jidlo); int vymesuj( int objem); }; Přístup pro třídu a potomky class Pes : public Zvire { private: enum t_stav { Stoji, Sedi, Lezi }; t_stav stav; public: Pes() { stav = Stoji; }; void sedni() { stav = Sedi; }; t_stav codela() { return stav; } }; přidaná položka položky předka metody předka Zvire pytlik; Pes azor; pytlik.jez(); azor.jez(); azor.sedni(); stav žaludek jez, vyměšuj sedni položky potomka metody potomka potomek obsahuje všechny položky a metody předka

Konstruktor a destruktor předka implicitní konstruktor předka (automaticky) class Zvire { ... ~Zvire() { printf( "zabijim zvire "); }; }; class Pes : public Zvire public: Pes() { stav = Stoji; }; Pes( int jidlo) : Zvire( jidlo) { stav = Stoji; }; ~Pes() { printf( "zabijim psa "); }; { Pes azor; ... } explicitní konstruktor předka konstruktory předků a vložených tříd se volají před konstruktorem potomka destruktor předka se vyvolá automaticky po ukončení destruktoru potomka zabijim psa zabijim zvire

Kompatibilita předka a potomka Potomka lze přiřadit do předka (platí i pro ukazatele) Předka NELZE přiřadit do potomka (platí i pro ukazatele) pes umí jíst, brouk neumí štěkat azor Zvire pytlik, *pz; Pes azor, *pp; pytlik = azor; pz = &azor; pytlik stav žaludek žaludek azor pytlik azor = pytlik; pp = &pytlik; stav žaludek žaludek ??? nelze

Polymorfismus Zvíře Pes Pitbul Člověk odlišné chování potomků – pozdní vazba (late binding) Zvíře Pes Pitbul jez jez jez sní maso sní hodně masa najde něco v přírodě Člověk jez jde do restaurace

Polymorfismus - motivace Tohle není polymorfismus ! class Zvire { jez() { priroda(); }; }; class Pes : public Zvire { jez() { maso(1); }; class Pitbul : public Pes { jez() { maso(10); }; class Clovek : public Zvire { jez() { hospoda(); }; Zvire pytlik; Pes punta; Pitbul zorro; Clovek pepa; pytlik.jez(); // priroda(); punta.jez(); // maso(1); zorro.jez(); // maso(10); pepa.jez(); // hospoda(); 'normální' vlastnost tříd zakrývání metod Při překladu je známo ze které třídy se volá metoda Každá třída má vlastní implementaci (tělo) metody jez

Polymorfismus – takto nelze do ukazatele na základní třídu (předka) dám ukazatel na nově vytvořený objekt odvozené třídy (potomka) Zvire* z; z = new Pes; z->jez(); // priroda(); z = new Clovek; z je ukazatel na zvíře volá se Zvire::jez() pokus – 'na tvrdo' chci metodu potomka nelze - syntaktická chyba pes není předkem zvířete Zvire* z; z = new Pes; z->Pes::jez(); // priroda(); z = new Clovek; z->Clovek::jez(); // priroda();

Polymorfismus – takto bych to chtěl chtěl bych, aby se volaly 'správné' metody Zvire* z; z = new Pes; z->jez(); // maso(1); z = new Clovek; z->jez(); // hospoda(); Zvire* naseRodina[3]; naseRodina[0] = new Clovek; naseRodina[1] = new Pes; naseRodina[2] = new Pitbul; for( int i = 0; i < 3; i++) naseRodina[i]->jez(); Chci pokaždé se zavolat jinou metodu Rozlišení metody se musí dít za běhu

Virtuální funkce - deklarace magické klíčové slovo virtual class Zvire { virtual jez() { priroda(); }; }; class Pes : public Zvire { virtual jez() { maso(1); }; class Pitbul : public Pes { virtual jez() { maso(10); }; class Clovek : public Zvire { virtual jez() { hospoda(); }; každý objekt si s sebou nese informaci kterou virtuální funkci používá

Virtuální funkce - implementace Zvire * z; z = new Zvire; z = new Pes; Pes Zvire stav žaludek tabulka virtuálních funkcí žaludek jez jez Zvire::jez() { priroda(); }; Pes::jez() { maso(1); }; z->jez(); zavolá se správná metoda podle tabulky virtuálních funkcí

Virtuální funkce a konstruktory a destruktory v konstruktoru a destruktoru se vždy volá metoda vytvářeného/rušeného objektu nejdřív se zavolá konstruktor předka class A { public: virtual f(); A() { f(); }; // A::f ~A() { f(); }; // A::f g() { f(); }; // A/B::f }; class B : public A { public: virtual f(); B() { f(); }; // A::A B::f ~B() { f(); }; // B::f A::~A g() { f(); }; // B::f }; určí se za běhu podle skutečného typu objektu nejdřív se provede kód destruktoru, pak se zavolá destruktor předka

Volání virtuálních funkcí class A { public: virtual f(); }; class B : public A { public: virtual f(); }; A a; // A::A B b; // B::B A * paa = &a; A * pab = &b; B * pbb = &b; // B * pba = &a; nelze!! (předka do potomka) a.f(); // A::f b.f(); // B::f paa->f(); // A::f pab->f(); // B::f pbb->f(); // B::f b.A::f(); // A::f b.B::f(); // B::f a.B::f(); // NE! paa->A::f(); // A::f pab->A::f(); // A::f pab->B::f(); // NE! pbb->A::f(); // A::f pbb->B::f(); // B::f pozdní vazba kvalifikované volání paa a A::f pab b B::f pbb

Abstraktní třída, čistě virtuální funkce nelze vytvořit objekt společný předek int armada; class Vojak { public: enum THod { vojin, desatnik, porucik, general }; Vojak( THod hod = vojin) { hodnost=hod; armada++; }; virtual void pal() = 0; virtual ~Vojak() { armada--; }; private: THod hodnost; }; pure virtual function ⇒ abstraktní třída společné rozhraní class Samopal {}; class Kalasnikov : public Samopal {}; class Pesak : public Vojak { private: Samopal* sam; public: Pesak( THod hod=vojin) : Vojak( hod) { sam = new Kalasnikov; }; virtual void pal() { sam->pal(); }; virtual ~Pesak() { delete sam; }; }; POZOR!!! Nutný virtuální destruktor

Abstraktní třídy, virtuální destruktory pokud by ~Vojak nebyl virtuální // Vojak v; // NELZE – abstraktní třída Pesak p; // OK – Pesak Vojin Pesak* pp = new Pesak; // OK pp->pal(); // Pesak::pal Vojak* pv = new Pesak; // OK pv->pal(); // Pesak::pal delete pp; // OK, Pesak::~Pesak delete pv; // !!! Vojak::~Vojak class Vojak { virtual ~Vojak() { armada--; }; }; class Pesak : public Vojak virtual ~Pesak() { delete sam; }; POZOR!!! nejsou-li destruktory virtuální, nezruší se samopal Řešení: virtuální destruktor

Nesprávné užití dědičnosti Letadlo není potomkem svého motoru Důkaz: Co když má dva motory... Násobná dědičnost? Ne: Je třeba je odlišit Jezevčík umí vyhnat lišku z nory... Myslivec s jezevčíkem tedy také... Myslivec není potomkem svého jezevčíka Důkaz: Nežere granule... Kompozice? Ne: Nerodí se zároveň Mlok není potomkem ryby a savce Důkaz: Nemá dvě hlavy... Virtuální dědičnost? Ne: Nekojí Tlačítko není potomkem obdélníku a textu Kompozice Skládání velkých objektů z malých C++: Třída s datovými položkami Delegace Převedení funkčnosti na jiný objekt C++: Ukazatel Společný abstraktní předek Obratlovec Vizuální objekt

Prostory jmen (namespaces) zapouzdření identifikátorů prevence kolizí (velké projekty, knihovny) stejné identifikátory v různých prostorech jmen definice prostoru jmen namespace aa { int p; int f1( int x) { return x + p; } int f2( int x, int y); } int aa::f2( int x, int y) { return p * (x + y); aa::f1( aa::f2( 5, 6)); přístup k identifikátoru ze stejného prostoru definice funkce mimo prostor jmen přístup k identifikátorům přes ::

Prostory jmen prostor jmen se může opakovaně otevírat a zavírat explicitní přístup ke globálnímu identifikátoru ::id standardní knihovny – namespace std rozbalení std using namespace std; namespace aa { int p; int q; } int g( int n) { cout << (n + aa::p); int f3( int x) { return 1 + ::g( x); přístup do aa přístup k identifikátorům std znovuotevření prostoru aa přístup ke globálnímu identifikátoru

Prostory jmen a standardní knihovny stará konvence: stdio.h, ctype.h, iostream.h identifikátory v globálním prostoru jmen strlen, FILE nová konvence: cstdio, cctype, iostream identifikátory uzavřené do namespace std std::strlen, std::FILE standardní knihovny C++ Základní knihovny z C přejmenované podle nové konvence Rozšířené C++ knihovny iostream: znakový formátovaný vstup a výstup STL: Standard Template Library použití šablon kontejnery, iterátory, algoritmy

Vstup a výstup - proudy (streams) hierarchie tříd pro (formátovaný znakový) vstup a výstup jednotné rozhraní pro v/v do souborů a paměti, ... operátory << a >>, manipulátory motivace: rozšiřitelnost bezpečnost datum d( 12, 3, 2004); printf( "dnes je %?", d); int i; printf( "Jmenuji se %s", i); #include <iostream> using namespace std; int main() { int n; cout << "Rekni cislo: "; cin >> n; cout << "Mam vic: " << (n+1) << ", hec!" << endl; } definice základních tříd a manipulátorů ostream cout  FILE* stdout istream cin  FILE* stdin ostream& ostream::operator<< () istream& istream::operator>> ()

Streams – hierarchie tříd

Hlavičkové soubory <iostream> – základní operace, standardní v/v, manipulátory bez parametrů cin, cout, <<, >>, endl, ws, ... <iomanip> – manipulátory s parametry setw, setfill, ... <fstream> – vstup a výstup do souborů fstream, ifstream, ofstream, ... <strstream> - vstup a výstup do paměti (chytré řetězce) strstream, istrstream, ostrstream, ...

vytiskne podle aktuálního nastavení Manipulátory do proudu lze vkládat manipulátory – změní stav proudu endl pošle buffer na výstup a odřádkuje left, right zarovnávej doleva / doprava dec, hex v desítkové / šestnáctkové soustavě ws přeskoč bílé znaky (na vstupu) setw(int) šířka výstupního pole (jen pro následující číselnou položku) setfill(int) výplňkový znak ... a spousty dalších cout << "[" << setfill('.') << setw(5) << 17 << "]" << endl; [...17] nastaví výplňový znak nastaví šíři výstupu vytiskne podle aktuálního nastavení výstup

Výstup do souboru spojení proudu se souborem v konstruktoru způsob otevření ios::in, out, app, trunc, binary, ... Př: ios::in | ios::binary #include <fstream> using namespace std; int main() { fstream f( "C:\\src\\pokus.txt", ios::out); if( ! f) error(); f << "bubu" << endl; } třída pro souborový proud operator ! (ostream&) vrátí true když se operace nepodařila soubory není třeba zavírat, zavře je automaticky destruktor

Další metody vstupních proudů pro binární vstup a výstup nelze použít operátory << a >> Vstup get( kam, délka, koncový_znak) getline( kam, délka, koncový_znak) ignore( délka, koncový_znak) read( pole_znaků, délka) tellg() seekg( posun, odkud) unget() Výstup put( znak) write( pole_znaků, délka) tellp() seekp(posun, odkud) flush() ... a další int i = 17; ofstream f( "pokus.txt", ios::binary); if( ! f) error(); f.write( (char*)&i, sizeof( i)); pole bajtů a jejich počet

Spřátelené funkce – vlastní výstup class Complx { private: int re, im; public: Complx( int _re = 0, int _im = 0) { re = _re; im = _im; }; friend ostream& operator<<( ostream& s, Complx& c) { return s << c.re << "+" << c.im << "i"; }; }; Complx x(1,2); cout << x << endl; POZOR! Toto není metoda třídy! spřátelená (friend) funkce může přistupovat k privátním položkám

Šablony množina funkcí/tříd lišících se pouze typem parametrů/položek vzor, podle kterého překladač vytvoří funkci nebo třídu (instanci) pro konkrétní typ Typový parametr T nahrazuje skutečný typ místo typename lze class Definice šablony funkce template <typename T> T max( T a, T b) { return a > b ? a : b; }; int x = 10, y = 20; double m = 1.1, n = 2.2; cout << max(x,y) << max(m,n) << endl; int max( int a, int b) double max( double a, double b)

Šablony tříd - definice template<typename T> class Guma { private: int size; T* array; public: const int default_size = 10; Guma( int _size = default_size) { size = _size; array = new T[size]; }; ~Guma() { delete array; } T& operator[] (int n); }; int main() Guma<int> ip(5); ip[3] = 999; size: 5 array: pole neznámého typu ? 3 4 2 1 instance šablony třídy definice proměnné přetížený operator[]

Šablony metod, instance šablon instance šablony třídy definice typu template<typename T> class Guma { private: int size; T* array; public: T& operator[] (int n); }; template<typename T> T& Guma<T>::operator[] (int n) { if( n >= size) { T* na = new T[ n + 1]; for( int i = 0; i < size; i++) na[i] = array[i]; delete array; array = na; size = n + 1; } return array[n]; struct Krabice { int a, b; char jm[10]; }; typedef Guma<Krabice> polekrab; int main(int argc, char* argv[]) Guma<int> ip(5); polekrab pk; ip[3] = 999; pk[12].a = ip[3]; definice šablony metody pk[i] je typu Krabice&

STL – Standard Template Library kontejnery – datové struktury pro ukládání dat a manipulaci s nimi iterátory – třídy pro přístup k datům kontejnerů algoritmy – základní algoritmy nad kontejnery (třídění, procházení, hledání) další pomocné třídy – alokátory, komparátory, funktory ... obousměrný seznam list<int> sez; sez.push_front( 1); sez.push_back( 2); sez.push_front( 3); list<int>::iterator i; for( i = sez.begin(); i != sez.end(); i++) cout << "[" << *i << "]"; přidání prvku zepředu ... zezadu ... zepředu iterátor seznamu průchod seznamem přístup k datům přes iterátor – operator*

STL – kontejnery Sekvenční kontejnery Asociativní kontejnery uspořádané setříděné

STL – kontejnery Sekvenční kontejnery deque – dvoustranná fronta [dek] umožňuje v konst. čase přidávat na začátek i konec implementace typicky pomocí polí adaptéry (specializované použití i rozhraní): stack, queue, priority_queue vector – pole (gumové) přístup k prvku v konstantním čase jako vector se chová i string a standardní pole (T x[]) string – chytré řetězce =, +, += a mnoho dalších operací a metod list – dvousměrný seznam implementace: spojový seznam umožňuje v konstantním čase přidávat prvky na libovolné místo Asociativní kontejnery map, multimap – zobrazení, asociativní pole, slovník, mapa uspořádaná struktura indexovaná libovolným typem, pair: klíč, hodnota) set, multiset – množina, multimnožina každý prvek nejvýše jednou / vícekrát

STL – iterátory a metody kontejnerů kontejner<T>::iterator iterátor příslušného kontejneru T& iterator::operator* přístup k prvku přes iterátor begin(), end() iterátor na začátek / za(!) konec kontejneru push_front(), push_back() přidání prvku na začátek / konec pop_front(), pop_back() odebrání prvku ze začátku / konce – nevrací hodnotu! front(), back() prvek na začátku / konci operator[], at() přímý přístup k prvku insert(iterator,T) vložení prvku na místo určené iterátorem size(), empty(), clear() velikost / neprázdost / smazání kontejneru push(), pop(), top() přidání / odebrání / prvek na vrcholu zásobníku

STL – použití iterátorů vytvoření celočíselného vectoru pole p je iterátor do vector<int> jestli p už nedosáhl konce pole.end() vrátí iterátor za konec pole vector<int> pole; vector<int>::iterator p; for( p = pole.begin(); p != pole.end(); p++) cout << "[" << *p << "]"; pole.begin() vrátí iterátor na začátek pole *p (overl.) vrátí hodnotu prvku na nějž ukazuje iterátor p++ (overl.) zařídí, že p bude ukazovat na další prvek

STL – použití asociativního pole map<string,string> ts; ts["Filip"] = "605123456"; ts["Petra"] = "721334455"; ts["David"] = "723654321"; ts["Kuba"] = "222333444"; cout << "Telefon Petry: " << ts["Petra"] << endl; map<string,string>::iterator ti; for( ti = ts.begin(); ti != ts.end(); ti++) cout << ti->first << ": " << ti->second << endl; operator [] (const string&) vyhledání podle first ts: pair: string first string second pair<string,string> iterator::operator* ti->first ≡ (*ti).first

STL – algoritmy + mnoho dalších Inicializace fill Fills a sequence with an initial value fill_n Fills n positions with an initial value copy Copies a sequence into another sequence copy_backward Copies a sequence into another sequence generate Initializes a sequence using a generator generate_n Initializes n positions using a generator swap_ranges Swaps values from two parallel sequences Vyhledávání find Finds an element matching the argument find_if Finds an element satisfying a condition adjacent_find Finds consecutive duplicate elements find_first_of Finds one member of a seq. in another seq. find_end Finds the last occurr. of a sub-seq. in a seq. search Matches a sub-sequence within a sequence max_element Finds the maximum value in a sequence min_element Finds the minimum value in a sequence mismatch Finds first mismatch in parallel sequences Mazání remove Removes elements that match condition unique Removes all but first of duplicate values Ostatní for_each Applies a function to each element Transformace prvků reverse Reverses the elements in a sequence replace Replaces specific values with new value replace_if Replaces elements matching predicate rotate Rotates elements in a sequence around a point next_permutation Generates permutations in sequence prev_permutation Generates permutations in reverse seq. inplace_merge Merges two adjacent sequences into one random_shuffle Randomly rearranges elements in a seq. Třídění sort Sorts all elements make_heap Converts a range into a heap Skalární výpočty count Counts number of elements matching value count_if Counts elements matching predicate accumulate Reduces sequence to a scalar value equal Checks two sequences for equality lexicographical_compare Compares two sequences Výpočty generující sekvence transform Transforms each element partial_sum Generates sequence of partial sums adjacent_difference Gen. sequence of adjacent differences

STL – použití algoritmů vlastní funkce pro jeden prvek vyplní se náhodnými čísly void tiskni( int x) { cout << " [" << x << "]"; } vector<int> pole; vector<int>::iterator b, e, p; generate( b = pole.begin(), e = pole.end(), rand); for_each( b, e, tiskni); p = max_element( b, e); sort( p, e); unique( p, e); for_each( b, pole.end(), tiskni); pro každý prvek se zavolá funkce najde max. prvek vrátí iterátor !! pozor – může zneplatnit iterátor e setřídí část pole od max. prvku do konce odstraní duplicity

STL – chybová hlášení \SRC\templ\templ.cpp(101) : error C2664: 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::iterator __thiscall std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::insert(class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::iterator,const struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' : cannot convert parameter 1 from 'char [6]' to 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::iterator'

string Compare strings ==,!=,<,<=, >,>=, compare() ==,!=,<,<=, >,>=, compare() Concatenates strings + Replaces characters replace() Changes the number of characters (deletes or appends chars at the end) resize() Removes all characters (makes it empty) clear() Deletes characters erase() Inserts characters insert() Append characters +=,append(), push_back() Swaps values between two strings swap() Assign a new value =, assign() Destroys a string destructor Create or copy a string constructors Returns the allocator get_allocator() Provide reverse iterator support rbegin(), rend() Provide normal iterator support begin(), end() Search for a certain substring or character find functions Returns a certain substring substr() Returns the value as character array data() Returns the value as C-string c_str() Copies or writes the contents to a C-string copy() Writes the value to a stream << Read the value from a stream >>, getline() Access a character [], at() Returns the number of characters that can held without be reallocation capacity() Returns whether the string is empty empty() Returns the maximum possible number of characters max_size() Return the number of characters size(), length()

Výjimky Motivace: co dělat, když (knihovní) funkce zjistí chybu? nedostatek paměti, nelze otevřít soubor, nulový ukazatel, ... Vypsat zprávu na 'obrazovku' a skončit FUJ! Nikdy! Nastavit do globální funkce příznak chyby problém s více vlákny, nutnost neustále testovat Vrátit 'divnou' hodnotu takhle funguje většina knihovních funkcí C nepříliš praktické, testování každé funkce, vnořené testy divná hodnota nemusí existovat Co chceme: oddělit detekci výjimečné situace od jejího zpracování po výskytu 'chyby' (výjimečné situace) automaticky skočit na zpracování kulturně po sobě uklidit (volání destruktorů) Řešení v C++: mechanismus výjimek

Výjimky - jednoduchý příklad void mojefce( char* str) { if( ! str) throw runtime_error( "Nic!"); cout << str; } int main(int argc, char* argv[]) char* p = 0; try { mojefce( p); } catch( runtime_error& e) { cout << "Chyba: " << e.what() << endl; return 0; vyvolání výjimky typ výjimky standardní třída potomek exception pokusný blok try block handler(y) typ výjimky standardní metoda třídy runtime_error řetězec z konstruktoru

Výjimky - jednoduchý příklad char* mojefce( long n) { char* bigbigbig = new char[n]; cout << "Proslo to" << endl; return bigbigbig; } int main(int argc, char* argv[]) char* p = 0; try { mojefce( 2000000000); cout << "Vratil jsem se" << endl; } catch( runtime_error& e) { cout << "Chyba: " << e.what() << endl; return 0; pokud se nepovede naalokovat, nastane výjimka při výjimce se dále nepokračuje, hledá se nejbližší volný handler nalezený handler

Výjimky - pravidla k try bloku může být několik handlerů s různými typy try bloky mohou být vnořené výjimka může být vyvolána v libovolně zanořené funkci po vyvolání výjimky se řízení předá handleru s odpovídajícím typem před odchodem ze všech bloků se zavolají destruktory lokálních objektů předávaná hodnota nese informaci o výjimce typické použití: potomek standardní třídy exception i pro výjimky platí, že potomek může nahradit předka konstruktor runtime_error(string&), metoda string what() po ošetření výjimky pokračuje program za handlery try bloku při běhu bez výjimky se handlery ignorují (přeskočí) neošetřená výjimka – unhandled exception, konec programu

Specifikace výjimek funkcí Problém: jak programátor pozná které výjimky má ošetřovat? Řešení: funkce může specifikovat výjimky, které může vyvolat funkce může vyvolat výjimky těchto typů void mojefce( char* s) throw (runtime_error, mojechyba); int jinafce( void) throw(); char* tretifce( char* s); funkce nevyvolává žádnou výjimku funkce může vyvolat libovolnou výjimku

... co jsme neprobrali spoustu věcí jazyk protected, volatile, static, operátory .* a ->*, ukazatele na funkce a metody, ... vícenásobná dědičnost, protokoly RTTI, typeid, type_info static_cast, dynamic_cast, reinterpret_cast, const_cast podrobněji knihovny, zejména streams a STL, efektivní používání knihoven OOP counted pointers, mělké vs. hluboké kopie objektová paradigmata – zprávy, obálkové třídy, subtyping, forwarding hlouběji o objektovém návrhu, reusabilitě, efektivitě implementace funktory a jiné specialitky kdo chcete C++ opravdu profesionálně používat, přečtěte si literaturu (Meyers, Sutter) nebuďte líní – zkoušejte i jednoduché věci naprogramovat 'profesionálně'

Dodelat na priste Vice slajdu o pretezovani operatoru (i unarni) Vice slajdu o referenci Chytre retezce – pocitane odkazy