Similar presentations:
Objektově orientované programování
1. Objektově orientované programování
doc. RNDr. Jan Lánský, Ph.D.Katedra informatiky a matematiky 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)
[email protected]
2. 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.
3. 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
4. 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)
5. Obsah předmětu
ZS (PJC)LS (OOP)
C++
C++
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...
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
Datová abstrakce
vytvoření vlastního datového typu (abstract/user defined datové typy)
kompletní množina operací nad tímto typem
nelze rozumně rozšiřovat
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í
dále – generické
programování
šablony, STL
7. Třídy a objekty
Koncepční pohledobjekt: 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)
8. Třída zvíře v C++ - rozhraní
zvire.hdefinice třídy
rozhraní
(veřejné)
konstruktor
(inicializace)
metody
class Zvire
{
private:
int zaludek;
vnitřní stav
(privátní)
public:
Zvire() { zaludek = 1; };
Datová
položka
int zije() { return zaludek>0; };
int jez( int jidlo);
int vymesuj( int objem);
};
inline tělo
funkce
Deklarace
metody
9. Třída zvíře - implementace
zvire.hclass Zvire
{
Třída metody
private:
int zaludek;
public:
Zvire() { ... };
int zije() { ... };
int jez( int jidlo);
int vymesuj( int objem);
};
Přístup k
datům metody
Středník !!!
zvire.cpp
:: operátor
kvalifikace
#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
10. Třída zvíře - použití
zvire.hclass Zvire
{
private:
int zaludek;
mujprogram.cpp
Import rozhraní
public:
Zvire() { ... };
int zije() { ... };
int jez( int jidlo);
int vymesuj( int objem);
};
zaludek = 1
zaludek = 6
#include ”zvire.h”
.....
Automatický
konstruktor
{
.....
Zvire pytlik;
pytlik.jez(5);
pytlik.vymesuj(3);
zaludek = 3
if( ! pytlik.zije())
return -1;
-1 0 pytlik.vymesuj(4);
if( ! pytlik.jez(1))
return -2;
.....
}
Instance třídy
= objekt
11. Objekt - instance třídy
int Zvire::jez( int jidlo){
if( ! zije()) return 0;
return zaludek += jidlo;
}
dvě instance třídy
.....
Zvire pytlik, beruska;
pytlik.jez( 5);
beruska.jez( 1);
.....
Metoda třídy - ke kterému
objektu má přistupovat?
?
pytlik:
beruska:
zaludek
6
zaludek
2
12. this
Každá metoda dostane 'tajný' parametrthis – ukazatel na objekt
C
zvire:: znamena
zvire * this
C++
int jez( Zvire* this, int jidlo)
{
if( ! zije( this)) return 0;
return this->zaludek += jidlo;
}
int Zvire::jez( int jidlo)
{
if( ! zije()) return 0;
return zaludek += jidlo;
}
.....
Zvire pytlik, beruska;
.....
Zvire pytlik, beruska;
jez( &pytlik, 5);
jez( &beruska, 1);
.....
pytlik.jez( 5);
beruska.jez( 1);
.....
this->zije()
this->zaludek
this
pytlik:
zaludek
6
beruska:
zaludek
2
13. Reference
int x = 1, y = 2;int *px;
px = &x;
*px = 3;
reference
pouze inicializace
nelze měnit
int &ry = y;
ry = 4;
x:
3
:px
y:
4
:ry
reference i ukazatele jsou
reprezentovány adresou
return *px + ry;
x:
1
:a
y:
2
:b
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é
zpřehlednění kódu
přetěžování funkcí
14. 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;
}
Funkce se stejným identifikátorem
ale různým počtem parametrů
int pocitej( int a, int b)
{
return 2*a + b;
}
int pocitej( int a, const char* s)
{
return a + strlen( s);
}
pocitej( 1);
pocitej( 1, 2);
pocitej( 1, "ahoj");
Funkce se stejným počtem
ale různým typem parametrů
Správná funkce podle počtu a
typů skutečných parametrů
// int pocitej( int)
// int pocitej( int, int)
// int pocitej( int, char*)
15. Implicitní parametry
Některé parametry funkce mohou mít implicitní hodnotypokud nejsou všechny parametry implicitní – implicitní parametry odzadu
Při volání funkce lze implicitní parametry vynechat
použije se implicitní hodnota
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)
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í
16. Konstruktory
Implicitní konstruktorclass 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;
bez parametrů
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
17. Konstruktor s parametry
Tímto zakážemedeklarovat objekt bez
použití NEimplicitního
konstruktoru
class Clovek
{
private:
char jmeno[50];
Clovek();
Využití
public:
//Clovek() { jmeno[0] = 0; };
Clovek( char * jmeno) {
strcpy(this->jmeno, jmeno);
};
};
Clovek honza("Honza");
//Clovek petr;
Nejde, zakázali
jsme
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
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+( const Bod&);
Bod operator=( const Bod&);
};
implicitní parametry
implicitní konstruktor
přetížení operátoru +
a + b a.operator+(b)
a = b a.operator=(b)
Bod::Bod(0,0);
Bod a(1,2), b, c;
c = a + b;
c.operator=(a.operator+(b));
c.assign( a.add( b));
19. Přetěžování operátorů – těla metod
x this->xBod 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);
}
co to je ???
vytvoření dočasného objektu
konstruktor Bod::Bod(int, int)
reference
aktualizace stavu
kopie objektu
(hodnotou přiřazení je
přiřazovaná hodnota)
20. Přetěžování operátorů - pravidla
Většinu operátorů jazyka C++ lze definovat pro uživatelské datové typyNelze 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
21. Přetěžování operátorů – ekvivalence
Pozor! Pro předefinované operátory nemusí platit identity definované prozákladní typy:
a=a+b a+=b
Bod Bod::operator+=( const Bod& b)
{
x += b.x;
y += b.y;
return *this;
}
a[b] *(a+b)
Bod Bod::operator+=( const Bod& b)
{
return *this = *this + b;
}
this->operator=( this->operator+( b))
22. 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
23. Udržovatelnost kódu
class Bod{
public:
Bod( const Bod & b)
{ dosad(b); };
Bod operator=( const Bod & b)
{ dosad(b); return *this; };
Těla operátorů a konstruktorů
Public část před private
};
Funkce Get a Set
Těla metod vždy v *.cpp souboru
private:
int x, y;
void dosad( const Bod & b)
{ x=b.x; y=b.y; };
Private položky nejsou zajímavé
Datové položky vždy private
int GetX() {return x; };
int GetY() {return y; };
void SetX(int x) { this->x = x; }
void SetY(int y) { this->y = y; }
volání jiné funkce
Pro pozdější rozšíření
Lépe se hledá kde je implementované
Jména tříd
ToJeMojeTrida
Jména funkcí proměnných
mojePrvniFunkce
24. Objekt a ukazatel na objekt
C++ odlišuje objekt a ukazatel na nějRozdí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
25. Operátory new a delete
new: alokace paměti, zavolání konstruktorunení nutno testovat úspěšnost – mechanismus výjimek
delete: zavolání destruktoru, dealokace paměti
jako parametr lze i 0
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;
char* buf = new char[10];
strcpy( buf, “ahoj”);
...
delete[] buf;
dynamická alokace,
implicitní konstruktor
náhrada za malloc()
uvolnění paměti
další alokace,
explicitní konstruktory
alokace pole objektů
uvolnění paměti u alokovaných polí nutno []
26. Chytré řetězce – nápad
Práce s řetězci v C+ efektivní
– nepohodlná 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 = (char*) malloc( strlen(s1) + strlen(s2) + 2);
strcpy( s3, s1);
s3[ strlen(s1)] = ‘ ‘;
strcpy( s3 + strlen(s1) + 1, s2);
s3 = s1 + ‘ ‘ + s2;
s3 += “.”;
‘obyčejné‘ zřetězení – nechci se starat o to, kde sebrat
místo
27. Chytré řetězce - třída
class Str{
private:
char* buf;
ukazatel na
alokovaná data
public:
Str() { buf = 0; };
Str( const Str& s);
Str( const char* s);
implicitní konstruktor
prázdný řetězec
destruktor objekt si musí po sobě uklidit
delete přežije i 0, nemusím testovat
~Str() { delete[] buf; };
Str& operator=( const Str& s);
Str operator+( const Str& s);
operace s řetězci
int len() const { return buf ? strlen(buf) : 0; };
};
další metody
(délka řetězce)
Konstantní funkce,
nemodifikuje objekt
28. Destruktory
class Str{
private:
char* buf;
ukazatel na
alokovaná data
public:
alokace paměti
Str() { buf = 0; };
pro řetězec
Str( const char* s)
{ buf = new char[ strlen( s) + 1];
strcpy( buf, s); };
destruktor - automaticky
~Str() { delete[] buf; };
se volá při zrušení objektu
};
nemá argumenty
nic nevrací
29. Vyvolání destruktoru
v kostruktoru s1 se alokujepaměť pro řetězec
fce()
{
dynamická alokace sp2
Str s1 = “ahoj”;
Str* s2 = new Str( “babi”);
.....
delete zavolá destruktor
delete s2;
(a potom uvolní paměť)
.....
}
zde končí život s1
automaticky se vyvolá
destruktor
30. Řetězce – implementace
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)
{ ....
}
uklidit po
předchozím řetězci
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
31. 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);
privátní metoda –
alokace a kopírování
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; };
};
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 !!!
32. 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; };
};
Jde clear() přidat
do copy() ???
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);
}
}
alokace a kopírování
zkontrolovat
prázdný
řetězec
33. 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)
{
Str newstr;
newstr.buf = new char[ len() + strlen(s) + 1];
strcpy( newstr.buf, buf);
strcat( newstr.buf, s);
nelze návrat reference
return newstr;
(lokální dočasný objekt)
}
nové hodnoty VŽDY
vracet hodnotou
nový prázdný řetězec
místo na znaky
první operand
druhý operand
návratová hodnota
34. 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; };
};
lze vracet referencí
existující hodnota
operator+( char*)
operator+( Str&)
35. 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
36. Výstup
neprázdný obsahna stdout
‘normálně’ spojím řetězce
s mezerou ... a vytisknu
dočasný objekt
reference na s3
později si ukážeme
elegantnější řešení - streams
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();
37. ... 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;
};
38. Dědičnost
vztah tříd předek-potomek – hierarchiepř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
jez, vyměšuj
Pes
sedni, lehni
Člověk
uč_se
Pitbul
trhej
39. pes jako potomek zvířete - definice
class Zvire{
protected:
int zaludek;
Přístup pro
třídu a
potomky
public:
Zvire();
Zvire( int jidlo);
potomek
class Pes : public Zvire
(odvozená třída od)
{
Zvířete
private:
enum t_stav { Stoji, Sedi, Lezi };
t_stav stav;
přidaná položka
public:
Pes() { stav = Stoji; };
int zije();
int jez( int jidlo);
int vymesuj( int objem);
};
void sedni() { stav = Sedi; };
t_stav codela() { return stav; }
};
položky
předka
položky
potomka
metody
předka
žaludek
stav
jez, vyměšuj
sedni
potomek obsahuje všechny
položky a metody předka
metody
potomka
Zvire pytlik;
Pes azor;
pytlik.jez();
azor.jez();
azor.sedni();
40. Konstruktor a destruktor předka
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 "); };
};
{
implicitní konstruktor předka
(automaticky)
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
Pes azor;
...
}
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 ukazatele)
pes umí jíst, brouk neumí štěkat
Zvire pytlik, *pz;
Pes azor, *pp;
pytlik
žaludek
azor
žaludek
stav
pytlik = azor;
pz = &azor;
azor
azor = pytlik;
pp = &pytlik;
pytlik
žaludek
stav
nelze
žaludek
???
42. Polymorfismus
odlišné chování potomků – pozdní vazba (late binding)Zvíře
Pes
jez
jez
Pitbul
jez
sní maso
najde něco v
přírodě
Člověk
jez
jde do
restaurace
sní hodně
masa
43. Polymorfismus - motivace
class Zvire{ jez() { priroda(); };
};
class Pes : public Zvire
{ jez() { maso(1); };
};
class Pitbul : public Pes
{ jez() { maso(10); };
};
Tohle není polymorfismus !
Zvire pytlik;
Pes punta;
Pitbul zorro;
Clovek pepa;
pytlik.jez();
// priroda();
punta.jez();
// maso(1);
zorro.jez();// maso(10);
pepa.jez(); // hospoda();
class Clovek : public Zvire
{ jez() { hospoda(); };
};
Každá třída má vlastní
implementaci (tělo) metody jez
'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
do ukazatele na základní třídu (předka) dám ukazatelna nově vytvořený objekt odvozené třídy (potomka)
Zvire* z;
z je ukazatel na zvíře
volá se Zvire::jez()
z = new Pes;
z->jez(); // priroda();
z = new Clovek;
z->jez(); // priroda();
pokus – 'na tvrdo' chci
metodu potomka
Zvire* z;
z = new Pes;
z->Pes::jez();
nelze - syntaktická chyba
pes není předkem zvířete
// priroda();
z = new Clovek;
z->Clovek::jez(); // priroda();
45. Polymorfismus – takto bych to chtěl
chtěl bych, aby se volaly 'správné' metodyZvire* z;
Zvire* naseRodina[3];
z = new Pes;
z->jez(); // maso(1);
naseRodina[0] = new Clovek;
naseRodina[1] = new Pes;
naseRodina[2] = new Pitbul;
z = new Clovek;
z->jez(); // hospoda();
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
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
žaludek
jez
tabulka
virtuálních
funkcí
žaludek
jez
stav
Zvire::jez() { priroda(); };
z->jez();
Pes::jez() { maso(1); };
zavolá se správná metoda
podle tabulky virtuálních funkcí
48. Virtuální funkce a konstruktory a destruktory
v konstruktoru a destruktoru se vždyvolá metoda vytvářeného/rušeného
objektu
class A
{ public:
virtual f();
A() { f(); }; // A::f
~A() { f(); }; // A::f
g() { f(); }; // A/B::f
};
určí se za běhu podle
skutečného typu objektu
nejdřív se zavolá
konstruktor předka
class B : public A
{ public:
virtual f();
B() { f(); }; // A::A B::f
~B() { f(); }; // B::f A::~A
g() { f(); }; // B::f
};
nejdřív se provede kód destruktoru,
pak se zavolá destruktor předka
49. Volání virtuálních funkcí
aA::f
paa
pab
b
B::f
pbb
// A::f
// B::f
paa->f();
pab->f();
pbb->f();
// A::f
// B::f
// B::f
b.A::f();
b.B::f();
a.B::f();
paa->A::f();
pab->A::f();
pab->B::f();
pbb->A::f();
pbb->B::f();
// A::f
// B::f
// NE!
// A::f
// A::f
// NE!
// A::f
// B::f
kvalifikované volání
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();
b.f();
pozdní vazba
class A { public: virtual f(); };
class B : public A { public: virtual f(); };
50. Abstraktní třída, čistě virtuální funkce
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;
};
POZOR!!!
Nutný virtuální destruktor
abstraktní třída
nelze vytvořit objekt
společný předek
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; };
};
51. Abstraktní třídy, virtuální destruktory
pokud by ~Vojak nebyl virtuální// Vojak v;
Pesak p;
Pesak* pp = new Pesak;
pp->pal();
Vojak* pv = new Pesak;
pv->pal();
delete pp;
delete pv;
// NELZE – abstraktní třída
// OK – Pesak Vojin
// OK
// Pesak::pal
// OK
// Pesak::pal
// OK, Pesak::~Pesak
// !!! Vojak::~Vojak
POZOR!!! nejsou-li
destruktory virtuální,
nezruší se samopal
Řešení:
virtuální destruktor
class Vojak
{
virtual ~Vojak()
{ armada--; };
};
class Pesak
: public Vojak
{
virtual ~Pesak()
{ delete sam; };
};
52. Nesprávné užití dědičnosti
Letadlo není potomkem svého motoruDů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é...
Kompozice
Skládání velkých objektů z malých
C++: Třída s datovými položkami
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
Delegace
Převedení funkčnosti na jiný objekt
C++: Ukazatel
Společný abstraktní předek
Obratlovec
Vizuální objekt
53. Prostory jmen (namespaces)
zapouzdření identifikátorůprevence kolizí (velké projekty, knihovny)
stejné identifikátory v různých prostorech 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));
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 ::
54. Prostory jmen
prostor jmen se může opakovaně otevírat a zavíratexplicitní přístup ke globálnímu identifikátoru ::id
standardní knihovny – namespace std
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);
}
rozbalení std
přístup do aa
přístup k identifikátorům std
znovuotevření prostoru aa
přístup ke globálnímu
identifikátoru
55. Prostory jmen a standardní knihovny
stará konvence: stdio.h, ctype.h, iostream.hidentifiká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
56. Vstup a výstup - proudy (streams)
hierarchie tříd pro (formátovaný znakový) vstup a výstupjednotné 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);
#include <iostream>
using namespace std;
int main()
{
int n;
cout << "Rekni cislo: ";
cin >> n;
cout << "Mam vic: " << (n+1)
<< ", hec!" << endl;
}
int i;
printf( "Jmenuji se %s", i);
definice základních tříd a manipulátorů
ostream cout FILE* stdout
istream cin FILE* stdin
ostream& ostream::operator<< ()
istream& istream::operator>> ()
57. Streams – hierarchie tříd
58. 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, ...
59. Manipulátory
do proudu lze vkládat manipulátory – změní stav prouduendl
left, right
dec, hex
ws
setw(int)
setfill(int)
pošle buffer na výstup a odřádkuje
zarovnávej doleva / doprava
v desítkové / šestnáctkové soustavě
přeskoč bílé znaky (na vstupu)
šířka výstupního pole (jen pro následující číselnou položku)
výplňkový znak
... a spousty dalších
cout << "[" << setfill('.') << setw(5) << 17 << "]" << endl;
nastaví
výplňový
znak
nastaví šíři
výstupu
vytiskne podle
aktuálního nastavení
[...17]
výstup
60. Výstup do souboru
spojení proudu sesouborem v konstruktoru
třída pro
souborový
proud
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;
}
soubory není třeba zavírat,
zavře je automaticky destruktor
operator ! (ostream&)
vrátí true když se operace nepodařila
61. 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()
int i = 17;
ofstream f( "pokus.txt", ios::binary);
if( ! f) error();
f.write( (char*)&i, sizeof( i));
Výstup
put( znak)
write( pole_znaků, délka)
tellp()
seekp(posun, odkud)
flush()
... a další
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. Šablony
množina funkcí/tříd lišících se pouze typem parametrů/položekvzor, podle kterého překladač vytvoří funkci nebo třídu (instanci) pro konkrétní typ
Definice šablony funkce
Typový parametr T
nahrazuje skutečný typ
místo typename lze class
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)
64. Š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);
};
size:
5
pole
neznámého
typu
array:
0
1
2
3
4
?
?
?
?
?
instance šablony třídy
definice proměnné
int main()
{
Guma<int> ip(5);
ip[3] = 999;
přetížený operator[]
65. Šablony metod, instance šablon
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];
}
instance
šablony třídy
definice typu
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 nimiiterá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 ...
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 << "]";
obousměrný seznam
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
Sekvenční kontejneryAsociativní kontejnery
uspořádané
setříděné
68. STL – kontejnery
Sekvenční kontejnerydeque – 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
69. STL – iterátory a metody kontejnerů
kontejner<T>::iteratorT& iterator::operator*
iterátor příslušného kontejneru
přístup k prvku přes iterátor
begin(), end()
push_front(), push_back()
pop_front(), pop_back()
front(), back()
operator[], at()
insert(iterator,T)
size(), empty(), clear()
iterátor na začátek / za(!) konec kontejneru
přidání prvku na začátek / konec
odebrání prvku ze začátku / konce – nevrací hodnotu!
prvek na začátku / konci
přímý přístup k prvku
vložení prvku na místo určené iterátorem
velikost / neprázdost / smazání kontejneru
push(), pop(), top()
přidání / odebrání / prvek na vrcholu zásobníku
70. STL – použití iterátorů
vytvořeníceločíselného
vectoru pole
pole.begin()
vrátí iterátor na
začátek 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 << "]";
*p (overl.) vrátí
hodnotu prvku
na nějž ukazuje
iterátor
p++ (overl.)
zařídí, že p
bude ukazovat
na další prvek
71. 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;
pair<string,string> iterator::operator*
ti->first ≡ (*ti).first
operator [] (const string&)
vyhledání podle first
ts:
pair:
string first
string second
72. STL – algoritmy
Inicializacefill
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
unique
Removes elements that match condition
Removes all but first of duplicate values
Ostatní
for_each
Applies a function to each element
+ mnoho dalších
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
73. STL – použití algoritmů
vlastní funkce pro jeden prvekvyplní se
náhodnými
čísly
pro každý prvek
se zavolá funkce
najde max. prvek
vrátí iterátor
setřídí část pole od
max. prvku do konce
odstraní duplicity
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);
!! pozor – může
sort( p, e);
zneplatnit iterátor e
unique( p, e);
for_each( b, pole.end(), tiskni);
74. STL – chybová hlášení
\SRC\templ\templ.cpp(101) : error C2664: 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,classstd::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'
75. string
constructorsCreate or copy a string
size(), length()
Return the number of characters
destructor
Destroys a string
max_size()
=, assign()
Assign a new value
Returns the maximum possible number of
characters
swap()
Swaps values between two strings
empty()
Returns whether the string is empty
+=,append(),
push_back()
Append characters
capacity()
Returns the number of characters that can
held without be reallocation
insert()
Inserts characters
[], at()
Access a character
erase()
Deletes characters
>>, getline()
Read the value from a stream
clear()
Removes all characters (makes it empty)
<<
Writes the value to a stream
resize()
Changes the number of characters
(deletes or appends chars at the end)
copy()
Copies or writes the contents to a C-string
c_str()
Returns the value as C-string
replace()
Replaces characters
data()
Returns the value as character array
+
Concatenates strings
substr()
Returns a certain substring
==,!=,<,<=,
>,>=,
compare()
Compare strings
find functions
Search for a certain substring or character
begin(), end()
Provide normal iterator support
rbegin(), rend()
Provide reverse iterator support
get_allocator()
Returns the allocator
76. 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
Nastavit do globální funkce příznak chyby
FUJ! Nikdy!
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
77. 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
78. 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
79. Výjimky - pravidla
k try bloku může být několik handlerů s různými typytry 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
80. 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 může vyvolat libovolnou výjimku
funkce nevyvolává
žádnou výjimku
81. ... 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
spoustu věcí
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ě'
82. Dodelat na priste
Vice slajdu o pretezovani operatoru (i unarni)Vice slajdu o referenci
Chytre retezce – pocitane odkazy