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

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

Úvod do objektově orientovaného programování

Podobné prezentace


Prezentace na téma: "Úvod do objektově orientovaného programování"— 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++ Stroustrup 3rd ed

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

5 Obsah předmětu 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, ...

6 Paradigmata programování
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

7 Paradigmata programování
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í

8 Třídy a objekty Koncepční pohled Technický 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

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

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

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

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

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

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

15 Reference jako parametry
skutečné parametry odkazy na proměnné swap( int& a, int& b) { int c = a; a = b; b = c; } int x = 1, y = 2; swap( x, y); x: 1 :a y: 2 :b význam: zpřehlednění kódu přetěžování operátorů !

16 Přetěžování funkcí 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ů Funkce se stejným identifikátorem ale různým počtem parametrů 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) 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 Přetěžování operátorů - deklarace
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; implicitní parametry  implicitní konstruktor 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));

19 Přetěžování operátorů – těla metod
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); reference x  this->x aktualizace stavu kopie objektu (hodnotou přiřazení je přiřazovaná hodnota) co to je ??? vytvoření dočasného objektu konstruktor bod::bod(int, int)

20 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+=( bod& b) { x += b.x; y += b.y; return *this; } bod bod::operator+=( bod& b) { return *this = *this + b; } this->operator=( this->operator+( b))

21 copy konstruktor a operator=
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; není-li copy konstruktor nebo operator= definován, automaticky se vygeneruje copy konstruktor resp. operator= všech složek copy konstruktor deklarace nového objektu operator= přiřazení do existujícího obj.

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

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

24 ‘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á – 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); 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

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 ukazatel na alokovaná data class str { private: char* buf;
public: str() { buf = 0; }; str( char* s) { buf = new char[ strlen( s) + 1]; strcpy( buf, s); }; ~str() { delete[] buf; }; }; 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 v kostruktoru s1 se alokuje paměť 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

28 Řetězce – implementace
uklidit po předchozím řetězci 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) { 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

29 O něco lepší implementace
později si ukážeme ještě lepší – counted pointers 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; }; }; privátní metoda – provádí vlastní alokaci a kopírování často potřebujeme uklízet

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

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

32 Připojení řetězce 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; }; }; když už umíme + a = proč si neudělat += operator+( str&) operator+( char*)

33 Spolupráce str a int (jednotlivé znaky)
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); }; dodefinovat konstruktor, přiřazení a operace pro další typ dodefinovat konstruktor, přiřazení a operace pro další typ

34 Výstup později si ukážeme elegantnější řešení - streams
neprázdný obsah na stdout 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(); ‘normálně’ spojím řetězce s mezerou ... a vytisknu dočasný objekt reference na s3

35 ... and together class str { private: char* buf; void copy( char* s);
public: str() { buf = 0; }; str( str& s); str( char* s); str( int c); ~str(); 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 Dědičnost 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) protokoly - později zvíře pes pitbul jez, vyměšuj sedni, lehni trhej člověk uč_se

37 pes jako potomek zvířete - definice
class zvire { private: int zaludek; public: zvire(); zvire( int jidlo); int zije(); int jez( int jidlo); int vymesuj( int objem); }; 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; } };

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

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

40 Destruktor předka zabijim psa zabijim zvire 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 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 uk.) 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

42 Polymorfismus 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

43 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

44 Polymorfismus – takto nelze
z je ukazatel na zvíře volá se zvire::jez() zvire* z; z = new pes; z->jez(); // priroda(); z = new clovek; zvire* z; z = new pes; z->pes::jez(); // priroda(); z = new clovek; z->clovek::jez(); // priroda(); nelze (syntaktická chyba, pes není předkem zvířete)

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

47 Virtuální funkce - implementace
zvire * z; z = new zvire; z = new pes; pes zvire stav žaludek žaludek tabulka virtuálních funkcí tabulka virtuálních funkcí jez jez zvire::jez() { priroda(); }; pes::jez() { maso(1); }; z->jez(); 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 paa a A::f kvalifikované volání pab b B::f pbb

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)
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 ::

53 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 k identifikátorům std přístup do aa znovuotevření prostoru aa přístup ke globálnímu identifikátoru

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 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, snadné rozšiřování #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<< ( )

56 Streams – hierarchie tříd

57 Hlavičkové soubory <iostream> – základní operace, standardní v/v, manip. 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, ...

58 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ásl. číselnou položku) setfill(int) výplňkový znak ... a spousty dalších cout << "[" << setfill('.') << setw(5) << 17 << "]" << endl; [...17]

59 Výstup do souboru spojení proudu se souborem v konstruktoru
způsob otevření ios::in, out, app, trunc, binary, ... #include <fstream> using namespace std; int main() { fstream f( "C:\\src\\pokus.txt", ios::out); if( ! f) error(); f << "bubu" << endl; } 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 << 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() peek()

61 Další metody výstupních proudů
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; POZOR! Toto není metoda třídy! spřátelená (friend) funkce může přistupovat k privátním položkám

63 Šablony 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 Typový parametr T nahrazuje skutečný typ Definice šablony funkce template <class 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)

64 Šablony tříd - definice
pole neznámého typu template<class T> 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<int> ip(5); ip[3] = 999; size: 5 array: 1 2 3 4 ? instance šablony třídy definice proměnné přetížený operator[]

65 Šablony metod, instance šablon
instance šablony třídy definice typu template<class T> class guma { private: int size; T* array; public: T& operator[] (int n); }; template<class 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&

66 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*

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<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(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 STL – použití asociativního pole
map<string,string> ts; ts["Filip"] = " "; ts["Petra"] = " "; ts["David"] = " "; ts["Kuba"] = " "; 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; ts: pair: string first string second pair<string,string> iterator::operator*

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 find_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::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'

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 Výjimky - jednoduchý příklad
vyvolání výjimky 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; 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 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

76 ... co jsme neprobrali spoustu věcí Jazyk OOP
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


Stáhnout ppt "Úvod do objektově orientovaného programování"