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

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

Úvod do objektově orientovaného programování RNDr. Filip Zavoral, Ph.D. Katedra softwarového inženýrství MFF UK Malostranské nám. 25, Praha 1

Podobné prezentace


Prezentace na téma: "Úvod do objektově orientovaného programování RNDr. Filip Zavoral, Ph.D. Katedra softwarového inženýrství MFF UK Malostranské nám. 25, Praha 1"— Transkript prezentace:

1 Úvod do objektově orientovaného programování RNDr. Filip Zavoral, Ph.D. Katedra softwarového inženýrství MFF UK Malostranské nám. 25, Praha 1

2 Studijní povinnosti Přednáška 1.5 hod (od 9:00) Cvičení 1.5 hod (do 11:30) Následné osobní konzultace (45 min ve studovně) Klasifikovaný zápočet Příklady na cvičeních, 'domácí úkoly' Závěrečný test Odladit krátký program v omezeném čase Podmínka účasti – úspěšně absolvovaný test z PJC (ZS) Zápočtový program Libovolný prográmek, zůstává ze ZS, stačí C, nemusí být OOP Samostatně vypracovat během semestru

3 Literatura Bjarne Stroustrup: The C++ Programming Language Bruce Eckel: Myslíme v jazyku C++ James O. Coplien: Advanced C++ Programming Styles and Idioms Herb Sutter: Exceptional C++ Miroslav Virius: Pasti a propasti jazyka C++ Miroslav Virius: Programování v C++

4 ZS (PJC) LS (OOP) Obsah předmětu C++ C C

5 Paradigmata programování, OOP Objekty, zapouzdření, dědičnost Konstruktory a destruktory, new a delete Pozdní vazba, virtuální funkce Přetěžování funkcí, předefinování operátorů Abstraktní datové typy OO styly a idiomy Výjimky, šablony, knihovny, streams, STL, RTTI,... Obsah předmětu

6 Procedurální programování jakou akci mám provést vstup – výpočet (algoritmus) – výstup black box: procedura / funkce !! side effects, údržba Modulární programování rozdělení problému na komponenty procedury pracují nad daty - rozhraní black box: modul Paradigmata programování

7 Datová abstrakce vytvoření vlastního datového typu (abstract/user defined d.t.) kompletní množina operací nad tímto typem black box: datový typ !! nelze rozumně rozšiřovat Objektové programování dědičnost – obecné / konkrétní vlastnosti polymorfismus možnost pozdějších rozšíření Paradigmata programování

8 Koncepční pohled objekt: entita reagující na vnější podněty třída: monžina stejně reagujících entit Technický pohled objekt: struktura obsahující data a funkce, instance třídy datové položky, metody;angl. members třída: typ objektu Rozhraní – veřejné informace pro uživatele Implementace – (neveřejná) interní data a metody Třídy a objekty

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

10 Zvíře - implementace 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; } zvire.cpp třída metody :: operátor kvalifikace implementace (tělo) metody přístup k datům třídy

11 Zvíře - použití #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;..... } mujprogram.cpp instance třídy = objekt automaticky konstruktor import rozhraní zaludek = 1 zaludek = 3 -2  0

12 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);..... dvě instance třídy Metoda třídy - ke kterému objektu má přistupovat? zaludek6 2 pytlik: beruska: ?

13 this int jez( zvire* this, int jidlo) { if( ! zije( this)) return 0; return this->zaludek += jidlo; }..... zvire pytlik, beruska; jez( &pytlik, 5); jez( &beruska, 1);..... Každá metoda dostane tajný parametr this - ukazatel na objekt zaludek6 2 pytlik: beruska: C-style řešení this

14 Reference int x = 1, y = 2; int *px; px = &x; *px = 3; int &ry = y; ry = 4; return *px + ry; reference - pouze inicializace nelze měnit 3 x::px 4 y::ry reference i ukazatele jsou reprezentovány adresou

15 Reference jako parametry 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é 1 x::a:a 2 y::b:b význam: zpřehlednění kódu přetěžování operátorů !

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

17 Konstruktory class zvire { private: int zaludek; public: zvire() { zaludek = 1; }; zvire( int zal) { zaludek = zal; }; zvire( zvire& vzor) { zaludek = vzor.zaludek; }; }; zvire beruska; zvire pytlik( 20); zvire beberuska( beruska); zvire tlustoch = pytlik; implicitní konstruktor copy (kopírovací) konstruktor X(X&) různé zápisy copy konstruktoru

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

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

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

21 class bod { private: int x, y; public: bod( bod& b) { x=b.x; y=b.y; }; bod operator=( bod& b) { x=b.x; y=b.y; return *this; }; }; bod a(1,2); bod k, m(a), n = a; k = m; copy konstruktor a operator= copy konstruktor deklarace nového objektu operator= přiřazení do existujícího obj. není-li copy konstruktor nebo operator= definován, automaticky se vygeneruje copy konstruktor resp. operator= všech složek

22 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; delete pb; Operátory new a delete dynamická alokace, implicitní konstruktor náhrada za malloc() uvolnění paměti další alokace, explicitní konstruktory

23 bod& rb = *new bod( 1,2); rb = rb + rb; delete &rb; char* buf = new char[10]; strcpy( buf, “ahoj”);... delete[] buf; new a delete – pole a reference alokace pole objektů uvolnění paměti - u alokovaných polí nutno [] dynamická inicializace reference

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

25 Chytré řetězce - třída class str { private: char* buf; public: str() { buf = 0; }; str( str& s); str( char* s); ~str() { delete[] buf; }; str& operator=( str& s); str operator+( str& s); int len() { 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) operace s řetězci další metody (délka řetězce)

26 Destruktory class str { private: char* buf; public: str() { buf = 0; }; str( 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í objekt po sobě musí uklidit

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

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

29 class str { private: char* buf; void copy( char* s); public: str() { buf = 0; }; str( str& s) { copy( s.buf); }; str( char* s) { copy( s); }; ~str() { clear(); }; str& operator=( str& s) { clear(); copy( s.buf); return *this; }; str& operator=( char* s) { clear(); copy( s); return *this; }; void clear() { delete[] buf; }; }; O něco lepší implementace privátní metoda – provádí vlastní alokaci a kopírování často potřebujeme uklízet později si ukážeme ještě lepší – counted pointers

30 void str::copy( char* s) { if( !s || !*s) { buf = 0; } else { buf = new char[ strlen( s)+1]; if( buf) strcpy( buf, s); } Implementace kopírování zkontrolovat prázdný řetězec alokace a kopírování předpokládáme prázdný buf zařídí volající metoda – copy je private

31 str str::operator+( 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+( char* s) {.... } Zřetězení nový prázdný řetězec místo na znaky první operand druhý operand návratová hodnota

32 class str {.... public:.... str& operator=( str& s); str& operator=( char* s); str operator+( str& s); str operator+( char* s); str& operator+=( str& s) { *this = *this + s; return *this; }; str& operator+=( char* s) { *this = *this + s; return *this; }; }; Připojení řetězce když už umíme + a = proč si neudělat += operator+( str&) operator+( char*)

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

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

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

36 Vztah tříd předek-potomek – hierarchie Vícenásobná dědičnost specializace (potomek má/umí něco navíc) reusabilita (jiné chování bez změny pův. třídy) Dědičnost protokoly - později zvířepespitbul člověk jez, vyměšujsedni, lehnitrhej uč_se

37 pes jako potomek zvířete - definice class pes : public zvire { private: enum t_stav { Stoji, Sedi, Lezi }; t_stav stav; public: pes() { stav = Stoji; }; int sedni() { stav = Sedi; }; t_stav codela() { return stav; } }; potomek zvířete class zvire { private: int zaludek; public: zvire(); zvire( int jidlo); int zije(); int jez( int jidlo); int vymesuj( int objem); };

38 stav pes jako potomek – obsah objektu položky potomka jez, vyměšuj žaludek sedni položky předka metody předka metody potomka zvire pytlik; pes azor; pytlik.jez(); azor.jez(); azor.sedni(); potomek obsahuje všechny položky a metody předka

39 Konstruktor předka class pes : public zvire {... public: pes() { stav = Stoji; }; pes( int jidlo) : zvire( jidlo) { stav = Stoji; }; }; implicitní konstruktor předka (automaticky) explicitní konstruktor předka konstruktory předků a vložených tříd se volají před konstruktorem potomka

40 Destruktor předka class zvire {... ~zvire() { printf( "zabijim zvire "); }; }; class pes : public zvire {... ~pes() { printf( "zabijim psa "); }; }; { pes azor;... } destruktor předka se vyvolá automaticky po ukončení destruktoru potomka zabijim psa zabijim zvire

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

42 odlišné chování potomků – pozdní vazba (late binding) Polymorfismus najde něco v přírodě zvířepespitbul člověk jez sní maso sní hodně masa jde do restaurace

43 Polymorfismus - motivace 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(); Tohle není polymorfismus ! 'normální' vlastnost tříd zakrývání metod Při překladu je známo ze které třídy se volá metoda

44 Polymorfismus – takto nelze zvire* z; z = new pes; z->jez(); // priroda(); z = new clovek; z->jez(); // priroda(); z je ukazatel na zvíře volá se zvire::jez() 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();

45 Polymorfismus – takto bych to chtěl zvire* z; z = new pes; z->jez(); // maso(1); z = new clovek; z->jez(); // hospoda(); zvire* nase_rodina[3]; nase_rodina[0] = new clovek; nase_rodina[1] = new pes; nase_rodina[2] = new pitbul; for( int i = 0; i < 3; i++) z->jez(); Pokaždé se zavolá jiná metoda Rozlišení metody se děje za běhu Pokaždé se zavolá jiná metoda Rozlišení metody se děje za běhu

46 Virtuální funkce - deklarace 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(); }; }; magické klíčové slovo virtual každý objekt si s sebou nese informaci kterou virtuální funkci používá

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

48 Virtuální funkce a konstruktory 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 };

49 Volání virtuálních funkcí A a;// A::A B b;// B::B A * paa = &a; A * pab = &b; B * pbb = &b; 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 b B::f paa A::f a pab pbb kvalifikované volání

50 Abstraktní třída, čistě virtuální funkce int armada; class vojak { public: enum THod { vojin, desatnik, porucik, general }; private: THod hodnost; public: vojak( THod hod = vojin) { hodnost=hod; armada++; }; virtual void pal() = 0; ~vojak() { armada--; }; }; 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(); }; ~pesak() { delete sam; }; }; pure virtual function abstraktní třída POZOR!!! Nutný virtuální destruktor

51 Abstraktní třídy, virtuální destruktory vojak v;// NELZE – abstraktní třída pesak p;// OK – pesak vojin pesak* pp = new pesak;// OK pp->pal();// pesak::pal vojak* v = new pesak;// OK v->pal();// pesak::pal delete pp;// OK, pesak::~pesak delete v;// !!! 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

52 Prostory jmen (namespaces) 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)); zapouzdření identifikátorů prevence kolizí (velké projekty, knihovny) stejné identifikátory v různých prostorech jmen definice prostoru jmen přístup k identifikátoru ze stejného prostoru definice funkce mimo prostor jmen přístup k identifikátorům přes ::

53 using namespace std; namespace aa { int p; int q; } int g( int n) { cout << (n + aa::p); } namespace aa { int f3( int x) { return 1 + ::g( x); } 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 znovuotevření prostoru aa přístup do aa přístup ke globálnímu identifikátoru přístup k identifikátorům std

54 Prostory jmen a standardní knihovny stará konvence: stdio.h, ctype.h, iostream.h identifikátory v globálním prostoru jmen nová konvence: cstdio, cctype, iostream identifikátory uzavřené do namespace std 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

55 #include using namespace std; int main() { int n; cout << "Rekni cislo: "; cin >> n; cout << "Mam vic: " << (n+1) << ", hec!" << endl; } 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 >, manipulátory, snadné rozšiřování definice základních tříd a manipulátorů ostream cout  FILE* stdout istream cin  FILE* stdin ostream& ostream::operator<< ( )

56 Streams – hierarchie tříd

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

58 do proudu lze vkládat manipulátory – změní stav proudu endlpošle buffer na výstup a odřádkuje left, rightzarovnávej doleva / doprava dec, hexv desítkové / šestnáctkové soustavě wspřeskoč bílé znaky (na vstupu) setw(int)šířka výstupního pole (jen pro násl. číselnou položku) setfill(int)výplňkový znak... a spousty dalších [...17] cout << "[" << setfill('.') << setw(5) << 17 << "]" << endl; Manipulátory

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

60 Další metody vstupních proudů pro binární vstup a výstup nelze použít operátory > 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() peek()

61 Další metody výstupních proudů Výstup get( kam, délka, koncový_znak) 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

62 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; spřátelená (friend) funkce může přistupovat k privátním položkám POZOR! Toto není metoda třídy!

63 množina funkcí/objektů lišících se pouze typem parametrů/položek vzor, podle kterého překladač vytvoří funkci nebo třídu - instanci template 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; Šablony Definice šablony funkce Typový parametr T nahrazuje skutečný typ int max( int a, int b) double max( double a, double b)

64 template class guma { private: int size; T* array; public: enum { default_size = 10 }; guma( int _size = default_size) { size = _size; array = new T[size]; }; ~guma() { delete array; } T& operator[] (int n); }; int main(int argc, char* argv[]) { guma ip(5); ip[3] = 999; Šablony tříd - definice přetížený operator[] size: 5 array: ????? instance šablony třídy definice proměnné pole neznámého typu

65 template class guma { private: int size; T* array; public: T& operator[] (int n); }; template T& guma ::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]; } Šablony metod, instance šablon struct krabice { int a, b; char jm[10]; }; typedef guma polekrab; int main(int argc, char* argv[]) { guma ip(5); polekrab pk; ip[3] = 999; pk[12].a = ip[3]; instance šablony třídy definice typu pk[i] je typu krabice& definice šablony metody

66 list sez; sez.push_front( 1); sez.push_back( 2); sez.push_front( 3); list ::iterator i; for( i = sez.begin(); i != sez.end(); i++) cout << "[" << * i << "]"; STL – Standard Template Library obousměrný seznam 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... 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*

67 STL – kontejnery deque – dvoustranná fronta (implementace: pomocí polí) stack, queue, priority_queue – fronta, zásobník vector – pole list – dvousměrný seznam (implementace: spojový seznam) map, multimap – zobrazení, asociativní pole, slovník, mapa (uspořádaná struktura indexovaná libovolným typem, pair: klíč, hodnota) set – množina (každý prvek nejvýše jednou) string – chytré řetězce (+, +=, mnoho dalších operací a metod)

68 STL – iterátory a metody kontejnerů kontejner ::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(T), push_back(T) přidání prvku na začátek / konec pop_front(), pop_back() odebrání prvku ze začátku / konce – nevrací! push(T), pop() přidání a odebrání z fronty / zásobníku front(), back(), top() prvek na začátku fr. / konci fr. / vrcholu zás. 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

69 map ts; ts["Filip"] = " "; ts["Petra"] = " "; ts["David"] = " "; ts["Kuba"] = " "; cout << "Telefon Petry: " << ts["Petra"] << endl; map ::iterator ti; for( ti = ts.begin(); ti != ts.end(); ti++) cout first second << endl; STL – použití asociativního pole pair iterator::operator* ts: pair: string second string first

70 STL – generické algoritmy Algorithms initializing a sequence 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 Searching algorithms find Finds an element matching the argument find_if Finds an element satisfying a condition adjacent_find Finds consecutive duplicate elements f ind_first_of Finds one member of a sequence in another seq. find_end Finds the last occurrence 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 Removal algorithms remove Removes elements that match condition unique Removes all but first of duplicate values Algorithms for in-place transformations 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 partition Partitions elements into two groups stable_partition Partitions preserving original ordering next_permutation Generates permutations in sequence prev_permutation Generates permutations in reverse sequence inplace_merge Merges two adjacent sequences into one random_shuffle Randomly rearranges elements in a sequence Scalar generating algorithms count Counts number of elements matching value count_if Counts elements matching predicate accumulate Reduces sequence to a scalar value inner_product Gives inner product of two parallel sequences equal Checks two sequences for equality lexicographical_compare Compares two sequences Sequence generating algorithms transform Transforms each element partial_sum Generates sequence of partial sums adjacent_difference Generates sequence of adjacent differences Miscellaneous operations for_each Applies a function to each element of a collection

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

72 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 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

73 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; } Výjimky - jednoduchý příklad 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

74 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

75 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 void mojefce( char* s) throw (runtime_error, mojechyba); int jinafce( void) throw(); char* tretifce( char* s); funkce může vyvolat výjimky těchto typů funkce nevyvolává žádnou výjimku funkce může vyvolat libovolnou výjimku

76 ... co jsme neprobrali spoustu věcí Jazyk const, protected, volatile, static, operátory.* a ->*, ukazatele na funkce,... vícenásobná dědičnost, protokoly RTTI, typeid, type_info static_cast, dynamic_cast, reinterpret_cast podrobněji knihovny 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 spoustu věcí


Stáhnout ppt "Úvod do objektově orientovaného programování RNDr. Filip Zavoral, Ph.D. Katedra softwarového inženýrství MFF UK Malostranské nám. 25, Praha 1"

Podobné prezentace


Reklamy Google