+ All Categories
Home > Documents > Objektově orientované programování

Objektově orientované programování

Date post: 15-Jan-2016
Category:
Upload: errol
View: 46 times
Download: 1 times
Share this document with a friend
Description:
RND r. Jan Lánský, Ph.D. Katedra softwarového inženýrství MFF UK Katedra informatiky V Š FS (Autor původní verze slajd ů : Mgr. Zbyněk Winkler ) (Autor prapůvodní verze slajd ů : RND r. Filip Zavoral, Ph.D. ) ( Část slajdů převzata od : RND r. David Bednárek ) [email protected] - PowerPoint PPT Presentation
81
Objektově orientované programování RNDr. Jan Lánský, Ph.D. Katedra softwarového inženýrství MFF UK Katedra informatiky VŠFS (Autor původní verze slajdů: Mgr. Zbyněk Winkler) (Autor prapůvodní verze slajdů: RNDr. Filip Zavoral, Ph.D.) (Část slajdů převzata od: RNDr. David Bednárek) [email protected] http://kocour.ms.mff.cuni.cz/~lansky/
Transcript
Page 1: Objektově orientované programování

Objektově orientované programování

RNDr. Jan Lánský, Ph.D.Katedra softwarového inženýrství MFF UK

Katedra informatiky VŠFS

(Autor původní verze slajdů: Mgr. Zbyněk Winkler)(Autor prapůvodní verze slajdů: RNDr. Filip Zavoral, Ph.D.)

(Část slajdů převzata od: RNDr. David Bednárek)

[email protected]://kocour.ms.mff.cuni.cz/~lansky/

Page 2: Objektově orientované programování

Studijní povinnosti

Zápočet Aktivní účast na cvičeních (80 %)

Chybějící účast lze nahradit: Vypracováním a předvedením příkladů probraných na cvičení [v

semestru] Zápočtový test (praktický příklad, odladěný, 3 hodiny) [kdykoliv]

Zápočtový program Téma (do 2. přednášky) Specifikace (do 3. přednášky) Betaverze (do konce semestru) Finální verze (do 30.6.)

Zkouška Ústní, s přípravou na PC (2 hodiny) Na zkoušku lze jít i bez zápočtu

Page 3: Objektově orientované programování

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 STLHerb Sutter: Exceptional C++, More Exceptional C++Que: ANSI/ISO C++ Professional Programmer's HandbookBruce Eckel: Myslíme v jazyce C++James O. Coplien: Advanced C++ Programming Styles and IdiomsBjarne Stroustrup: The C++ Programming Language

ISO/IEC 14882, ANSI: Programming languages - C++ (1998, 2003)

Page 4: Objektově orientované programování

ZS (PJC) LS (OOP)

Obsah předmětu

C C

C++

C++

Paradigmata programování, OOPObjekty, zapouzdření, dědičnost, konstruktory a destruktoryPřetěžování funkcí, předefinování operátorůPozdní vazba, virtuální funkceAbstraktní datové typyŠablony, výjimky, prostory jmen.Objektové knihovny: streams, STLRTTI, OO styly a idiomy...

Page 5: Objektově orientované programování

Procedurální programování jakou akci mám provést vstup – výpočet (algoritmus) – výstup black box: procedura / funkce

Modulární programování rozdělení problému na komponenty procedury pracují nad daty - rozhraní black box: modul

Datová abstrakce vytvoření vlastního datového typu (abstract/user defined datové typy) kompletní množina operací nad tímto typem black box: datový typ

Objektové programování dědičnost – obecné / konkrétní vlastnosti Polymorfismus – odlišné chování potomků možnost pozdějších rozšíření zapouzdření

Paradigmata programování

side effects, údržba

nelze rozumně rozšiřovat

dále – generické programováníšablony, STL

Page 6: Objektově orientované programování

Koncepční pohled objekt: entita reagující na vnější podněty třída: množina stejně reagujících entit

Technický pohled objekt: struktura obsahující data a funkce, instance třídy (proměnná) třída: typ objektu – jednotná struktura dat, stejné operace nad daty

Zobecnění pojmu struktura (struct) Rozdíl mezi class a struct v C++ je nepatrný, užívání class je pouze

konvence deklarace třídy obsahuje

Deklarace datových položek (stejně jako v C) Funkce (metody), virtuální funkce a statické funkce Definice výčtových konstant a typů (včetně vnořených tříd)

Rozhraní – veřejné informace a služby pro uživateleImplementace – (neveřejná) interní data a metody (funkce)

Třídy a objekty

Page 7: Objektově orientované programování

Třída 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

vnitřní stav(privátní)

rozhraní(veřejné)

metody

zvire.h

konstruktor(inicializace) inline

tělo funkce

Datová položka

Deklarace metody

Page 8: Objektově orientované programování

Třída zvíře - implementace

#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;}

class Zvire{private: int zaludek;

public: Zvire() { ... };

int zije() { ... }; int jez( int jidlo); int vymesuj( int objem);};

zvire.hzvire.cpp

Třída metody

:: operátor kvalifikace

Implementace (tělo) metody

Přístup k datům metody

Středník !!!

Page 9: Objektově orientované programování

Třída 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;

.....

}

-1 0

class Zvire{private: int zaludek;

public: Zvire() { ... };

int zije() { ... }; int jez( int jidlo); int vymesuj( int objem);};

zvire.hmujprogram.cppImport

rozhraní

Automatický konstruktor

Instance třídy = objekt

zaludek = 1zaludek = 6zaludek = 3

Page 10: Objektově orientované programování

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

6zaludek

2zaludek

pytlik:

beruska:

?

Metoda třídy - ke kterému objektu má přistupovat?

Page 11: Objektově orientované programování

int Zvire::jez( int jidlo){ if( ! zije()) return 0; return zaludek += jidlo;}

..... Zvire pytlik, beruska;

pytlik.jez( 5); beruska.jez( 1);.....

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);.....

6zaludek 2zaludekpytlik: beruska:this

C C++

Každá metoda dostane 'tajný' parametr this – ukazatel na

objekt

zvire:: znamena

zvire * this

this->zije()

this->zaludek

Page 12: Objektově orientované programování

Reference

int x = 1, y = 2;int *px;px = &x;*px = 3;

int &ry = y;ry = 4;

return *px + ry;

referencepouze

inicializacenelze měnit

3x: :px

4y: :ry

reference i ukazatele jsou reprezentovány

adresou

swap( int& a, int& b){ int c = a; a = b; b = c;}

int x = 1, y = 2;swap( x, y);

skutečné parametryodkazy na proměnné

1x: :a

2y: :b

zpřehlednění kódupřetěžování funkcí

Page 13: Objektově orientované programování

Přetěžování funkcí

int pocitej( int x){ return x+1;}

int pocitej( int a, int b){ return 2*a + b;}

int pocitej( int a, const char* s){ return a + strlen( s);}

pocitej( 1); // int pocitej( int)pocitej( 1, 2); // int pocitej( int, int)pocitej( 1, "ahoj"); // int pocitej( int, char*)

Funkce 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ů

Funkce se stejným počtemale různým typem parametrů

Page 14: Objektově orientované programování

Implicitní parametry

Některé parametry funkce mohou mít implicitní hodnoty pokud nejsou všechny parametry implicitní – implicitní parametry

odzadu

Při volání funkce lze implicitní parametry vynechat použije se implicitní hodnota

Kdy použít přetěžování a kdy implicitní parametry? Stejný kód pro různý počet parametrů implicitní parametry Pro různé počty nebo typy parametrů různý kód přetěžování

Volá se stále stejná funkce int fce( int, int,

int)

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)

Page 15: Objektově orientované programování

Konstruktory

class Zvire{private: int zaludek;

public: Zvire() { zaludek = 1; }; Zvire( int zal) { zaludek = zal; }; Zvire( const Zvire& vzor) { zaludek = vzor.zaludek; };};

Zvire beruska;Zvire pytlik( 20);Zvire beberuska( beruska);Zvire tlustoch = pytlik;

různé zápisycopy

konstruktoru

Pro U≠T nejsou zcela ekvivalentní:U u;T t(u); // T::T( U&)T t = u; // T::T( T(u)) nebo

// T::T( u.operator T())zatím lze ignorovat

Konstruktor s parametry

Implicitní konstruktor

bez parametrů

Copy konstruktor X (const X&)

vytvoří objekt jako kopii jiného

Page 16: Objektově orientované programování

Konstruktor s parametry

class Clovek{private: char jmeno[50]; Clovek();

public://Clovek() { jmeno[0] = 0; }; Clovek( char * jmeno) { strcpy(this->jmeno, jmeno); };};

Clovek honza("Honza");//Clovek petr;

Tímto zakážeme deklarovat objekt

bez použití NEimplicitního konstruktoru

Nejde, zakázali jsme

Využití Předání nastavení objektu Šetří řádky kódu

Zakázat implicitiní konstruktor

Dobře rozvážit zda zakázat Bezpečnost proti nezadání

klíčové hodnoty identifikátor

Page 17: Objektově orientované programování

class Bod{private: int x, y;

public: Bod( int xx=0, int yy=0) { x=xx; y=yy; };

Bod operator+( const Bod&); Bod operator=( const Bod&);};

Bod a(1,2), b, c;c = a + b;

Přetěž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);

Page 18: Objektově orientované programování

Bod Bod::operator=( const Bod& b){ x = b.x; y = b.y; return *this;}

Bod Bod::operator+( const Bod& b){ return Bod( x+b.x, y+b.y);}

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

Page 19: Objektově orientované programování

Přetěžování operátorů - pravidla

Většinu operátorů jazyka C++ lze definovat pro uživatelské datové typy Nelze předefinovat tyto operátory: .  .*  ::   ? :  sizeof

Alespoň jeden z operandů musí být třída nebo výčtový typ nebo reference na ně

Nelze předefinovat operace na číselných typech a ukazatelích

Předefinováním nelze měnit prioritu a asociativitu operátorů

Pro předefinované operátory nemusí platit identity definované pro základní typy

++a nemusí být ekvivalentní a=a+1 a[b] nemusí být ekvivalentní *(a+b) ani b[a]

je však velmi doporučeno dodržovat běžnou sémantiku

Pro předefinované operátory && a || neplatí pravidla o zkráceném vyhodnocování

Typy skutečných operandů nemusejí přesně odpovídat typům formálních parametrů

stejná pravidla jako pro přetížené funkce

Page 20: Objektově orientované programování

Bod Bod::operator+=( const 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+=b a[b] *(a+b)

Přetěžování operátorů – ekvivalence

Bod Bod::operator+=( const Bod& b){ return *this = *this + b; }

this->operator=( this->operator+( b))

Page 21: Objektově orientované programování

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;

copy konstruktor a operator=

copy konstruktordefinice nového objektu

operator=přiřazení do existujícího

objektu

není-li copy konstruktor nebo operator=

definován, automaticky se vygeneruje copy konstruktor resp.

operator= všech složek

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

Page 22: Objektově orientované programování

Udržovatelnost kódu

Těla operátorů a konstruktorů volání jiné funkce

Public část před private Private položky nejsou zajímavé

Datové položky vždy private Funkce Get a Set

Těla metod vždy v *.cpp souboru Pro pozdější rozšíření Lépe se hledá kde je

implementované

Jména tříd ToJeMojeTrida

Jména funkcí proměnných mojePrvniFunkce

class Bod{public: Bod( const Bod & b) { dosad(b); };

Bod operator=( const Bod & b) { dosad(b); return *this; };

int GetX() {return x; }; int GetY() {return y; }; void SetX(int x) { this->x = x; } void SetY(int y) { this->y = y; } private: int x, y; void dosad( const Bod & b) { x=b.x; y=b.y; };

};

Page 23: Objektově orientované programování

class Zvire {.....}; Zvire * pytlik; Zvire beruska;

pytlik = &beruska; pytlik = new Zvire;

C++ odlišuje objekt a ukazatel na něj Rozdíl oproti jiným jazykům

Java, JavaScript, PHP, VisualBasic, ... Analogie s chováním stuct v C Ukazatel nelze použít dokud není splněna jedna z možností:

Přiřazen existující objekt Reference

Dynamicky vytvořen nový objekt Operátor new

Objekt a ukazatel na objekt

Nevzniká tu žádný objekt

vzniká nový objekt

Page 24: Objektově orientované programování

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í

konstruktornáhrada za malloc()

uvolnění paměti

další alokace,explicitní

konstruktory

char* buf = new char[10];strcpy( buf, “ahoj”);...delete[] buf;

alokace pole objektů

uvolnění paměti -u alokovaných polí

nutno []

new: alokace paměti, zavolání konstruktoru není nutno testovat úspěšnost – mechanismus výjimek

delete: zavolání destruktoru, dealokace paměti jako parametr lze i 0

Page 25: Objektově orientované programování

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á a těžkopádná – časté chybyChtěl bych: přiřazování, zřetězení, automatická alokace místa

s3 = (char*) malloc( strlen(s1) + strlen(s2) + 2);strcpy( s3, s1);s3[ strlen(s1)] = ‘ ‘;strcpy( s3 + strlen(s1) + 1, s2);

Page 26: Objektově orientované programování

Chytré řetězce - třída

class Str{private: char* buf;

public: Str() { buf = 0; }; Str( const Str& s); Str( const char* s);

~Str() { delete[] buf; };

Str& operator=( const Str& s); Str operator+( const Str& s);

int len() const { return buf ? strlen(buf) : 0; };};

ukazatel na alokovaná data

implicitní konstruktor

prázdný řetězec

destruktor objekt si musí po sobě uklidit

delete přežije i 0, nemusím testovat

operace s řetězci

další metody(délka řetězce)

Konstantní funkce, nemodifikuje objekt

Page 27: Objektově orientované programování

Destruktory

class Str{private: char* buf;

public: Str() { buf = 0; }; Str( const char* s) { buf = new char[ strlen( s) + 1]; strcpy( buf, s); };

~Str() { delete[] buf; };};

ukazatel na alokovaná

data

alokace paměti pro

řetězec

destruktor - automaticky se volá při zrušení objektu

nemá argumentynic nevrací

Page 28: Objektově orientované programování

Vyvolání destruktoru

fce(){ Str s1 = “ahoj”; Str* s2 = new Str( “babi”); ..... delete s2; .....}

v kostruktoru s1 se alokuje paměť pro

řetězec

dynamická alokace sp2

delete zavolá destruktor

(a potom uvolní paměť)

zde končí život s1automaticky se vyvolá

destruktor

Page 29: Objektově orientované programování

Ř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 popředchozím

řetězciprá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ě

Page 30: Objektově orientované programová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; };};

O něco lepší implementace

privátní metoda –alokace a kopírování

často potřebujeme uklízet

později si ukážeme ještě lepší – counted

pointers

konstruktory: jen alokace a kopírování

přiřazení: i uklizení a návratová hodnota

!!! buf = 0; nebo private !!!

Page 31: Objektově orientované programování

void Str::copy( const 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

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() ???

Page 32: Objektově orientované programování

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); return newstr;}

Zřetězení

nový prázdný řetězec

místo na znaky

první operand

druhý operand

návratová hodnota

nelze návrat reference (lokální dočasný objekt)nové hodnoty VŽDY vracet

hodnotou

Page 33: Objektově orientované programování

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; };};

Připojení řetězce

když už umíme + a =proč si neudělat +=

operator+( Str&)

operator+( char*)

lze vracet referencí

existující hodnota

Page 34: Objektově orientované programování

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);};

Str a jednotlivé znaky

dodefinovat konstruktor, přiřazení a operace pro

další typ

Page 35: Objektově orientované programování

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();

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

Page 36: Objektově orientované programování

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();

... and together

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;};

Page 37: Objektově orientované programování

vztah tříd předek-potomek – hierarchie přesnější názvosloví: základní (base) / odvozená třída (derived class)

vícenásobná dědičnost dvakrát měř, jednou řež, protokoly

specializace potomek má/umí něco navíc

reusabilita jiné chování bez změny původní třídy

Dědičnost

Zvíře Pes Pitbul

Člověk

jez, vyměšuj

sedni, lehni trhej

uč_se

Page 38: Objektově orientované programování

pes jako potomek zvířete - definice

class Pes : public Zvire{private: enum t_stav { Stoji, Sedi, Lezi }; t_stav stav;

public: Pes() { stav = Stoji; };

void sedni() { stav = Sedi; }; t_stav codela() { return stav; }};

potomek(odvozená třída

od)Zvířete

class Zvire{protected: int zaludek;

public: Zvire(); Zvire( int jidlo);

int zije(); int jez( int jidlo); int vymesuj( int objem);};

přidaná položka

položkypotomka

jez, vyměšujstav

žaludeksedni

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

Přístup pro třídu a

potomky

Page 39: Objektově orientované programování

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 "); };};

{ Pes azor; ...}

destruktor předka se vyvolá automaticky po ukončení destruktoru

potomka

zabijim psa

zabijim zvire

implicitní konstruktor předka

(automaticky)

explicitní konstruktor předka

konstruktory předků a vložených tříd se volají

před konstruktorem potomka

Page 40: Objektově orientované programování

Potomka lze přiřadit do předka (platí i pro ukazatele)Předka NELZE přiřadit do potomka (platí i pro ukazatele)

Kompatibilita předka a potomka

pes umí jíst, brouk neumí štěkat

azorZvire pytlik, *pz;Pes azor, *pp;

pytlik = azor;pz = &azor;

azor = pytlik;pp = &pytlik;

stav

žaludek

pytlik

žaludek

stav

žaludek žaludek

pytlikazor

???nelz

e

Page 41: Objektově orientované programování

odlišné chování potomků – pozdní vazba (late binding)

Polymorfismus

najde něco v přírodě

Zvíře Pes Pitbul

Člověk

jez jez jez

jez

sní maso sní hodně masa

jde do restaurace

Page 42: Objektově orientované programování

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řídzakrývání metod

Při překladu je známoze které třídy se volá

metoda

Každá třída má vlastní implementaci (tělo)

metody jez

Page 43: Objektově orientované programování

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

Zvire* z;

z = new Pes;z->Pes::jez(); // priroda();

z = new Clovek;z->Clovek::jez(); // priroda();

do ukazatele na základní třídu (předka) dám ukazatel na nově vytvořený objekt odvozené

třídy (potomka)

pokus – 'na tvrdo' chci metodu potomka

nelze - syntaktická chyba

pes není předkem zvířete

Page 44: Objektově orientované programování

Polymorfismus – takto bych to chtěl

Zvire* z;

z = new Pes;z->jez(); // maso(1);

z = new Clovek;z->jez(); // hospoda();

Zvire* naseRodina[3];

naseRodina[0] = new Clovek;naseRodina[1] = new Pes;naseRodina[2] = new Pitbul;

for( int i = 0; i < 3; i++) naseRodina[i]->jez();

Chci pokaždé se zavolat jinou metodu

Rozlišení metody se musí dít za běhu

chtěl bych, aby se volaly 'správné' metody

Page 45: Objektově orientované programování

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á

Page 46: Objektově orientované programování

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á metodapodle tabulky virtuálních

funkcí

Page 47: Objektově orientované programování

Virtuální funkce a konstruktory a destruktory

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

};

nejdřív se zavolá konstruktor

předka

nejdřív se provede kód destruktoru, pak se zavolá

destruktor předka

v konstruktoru a destruktoru se vždy volá metoda

vytvářeného/rušeného objektu

určí se za běhu podle skutečného typu

objektu

Page 48: Objektově orientované programování

Volání virtuálních funkcí

class A { public: virtual f(); };class B : public A { public: virtual f(); };

A a; // A::A

B b; // B::B

A * paa = &a;

A * pab = &b;

B * pbb = &b;

// B * pba = &a; nelze!! (předka do potomka)

a.f(); // A::f

b.f(); // B::f

paa->f(); // A::f pab->f(); // B::f

pbb->f(); // B::f

b.A::f(); // A::f

b.B::f(); // B::f

a.B::f(); // NE!

paa->A::f(); // A::f

pab->A::f(); // A::f

pab->B::f(); // NE!

pbb->A::f(); // A::f

pbb->B::f(); // B::f

pozd

vazb

a

bB::f

paaA::f

a

pab

pbb

kvalifi

kovan

é

volá

Page 49: Objektově orientované programování

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;};

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; };};

pure virtual function

⇒ abstraktní třídaspolečné rozhraní

POZOR!!!Nutný virtuální

destruktor

abstraktní třída nelze vytvořit

objektspolečný předek

Page 50: Objektově orientované programování

Abstraktní třídy, virtuální destruktory

// Vojak v; // NELZE – abstraktní třídaPesak p; // OK – Pesak VojinPesak* pp = new Pesak; // OKpp->pal(); // Pesak::palVojak* pv = new Pesak; // OKpv->pal(); // Pesak::paldelete pp; // OK, Pesak::~Pesakdelete pv; // !!! Vojak::~Vojak

class Vojak{ virtual ~Vojak() { armada--; };};

class Pesak : public Vojak{ virtual ~Pesak() { delete sam; };};

POZOR!!! nejsou-li destruktory

virtuální,nezruší se samopal Řešení:

virtuální destruktor

pokud by ~Vojak nebyl virtuální

Page 51: Objektově orientované programování

Nesprávné užití dědičnosti

Letadlo není potomkem svého motoru Důkaz: Co když má dva motory... Násobná dědičnost? Ne: Je třeba je odlišit

Jezevčík umí vyhnat lišku z nory... Myslivec s jezevčíkem tedy také...

Myslivec není potomkem svého jezevčíka Důkaz: Nežere granule... Kompozice? Ne: Nerodí se zároveň

Mlok není potomkem ryby a savce Důkaz: Nemá dvě hlavy... Virtuální dědičnost? Ne: Nekojí

Tlačítko není potomkem obdélníku a textu

Kompozice Skládání velkých objektů z malých C++: Třída s datovými položkami

Delegace Převedení funkčnosti na jiný objekt C++: Ukazatel

Společný abstraktní předek Obratlovec Vizuální objekt

Page 52: Objektově orientované programování

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

Page 53: Objektově orientované programování

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íratexplicitní přístup ke globálnímu identifikátoru ::idstandardní 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

Page 54: Objektově orientované programování

Prostory jmen a standardní knihovny

stará konvence: stdio.h, ctype.h, iostream.h identifikátory v globálním prostoru jmen

strlen, FILE

nová konvence: cstdio, cctype, iostream identifikátory uzavřené do namespace std

std::strlen, std::FILE

standardní knihovny C++ Základní knihovny z C přejmenované podle nové konvence Rozšířené C++ knihovny iostream: znakový formátovaný vstup a výstup STL: Standard Template Library

použití šablon kontejnery, iterátory, algoritmy

Page 55: Objektově orientované programování

#include <iostream>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ýstupjednotné rozhraní pro v/v do souborů a paměti, ...operátory << a >>, manipulátorymotivace:

rozšiřitelnost bezpečnost

definice základních tříd a manipulátorů

ostream cout FILE* stdout istream cin FILE* stdin

ostream& ostream::operator<< ()istream& istream::operator>> ()

datum d( 12, 3, 2004);printf( "dnes je %?", d);

int i;printf( "Jmenuji se %s", i);

Page 56: Objektově orientované programování

Streams – hierarchie tříd

Page 57: Objektově orientované programování

<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, ...

Hlavičkové soubory

Page 58: Objektově orientované programování

do proudu lze vkládat manipulátory – změní stav proudu

endl pošle buffer na výstup a odřádkujeleft, right zarovnávej doleva / dopravadec, hex v desítkové / šestnáctkové soustavěws přeskoč bílé znaky (na vstupu)setw(int) šířka výstupního pole (jen pro následující číselnou položku)setfill(int) výplňkový znak

... a spousty dalších

[...17]

cout << "[" << setfill('.') << setw(5) << 17 << "]" << endl;

Manipulátory

nastaví výplňový znak

nastaví šíři

výstupu

vytiskne podle aktuálního nastavení

výstup

Page 59: Objektově orientované programování

#include <fstream>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,

...Př: ios::in | ios::binary

operator ! (ostream&)vrátí true když se operace

nepodařilasoubory není třeba zavírat,zavře je automaticky

destruktor

třída pro souborový proud

Page 60: Objektově orientované programování

Další metody vstupních proudů

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

pro binární vstup a výstup nelze použít operátory << a >>

Výstup put( znak) write( pole_znaků, délka) tellp() seekp(posun, odkud) flush()

... a další

int i = 17;ofstream f( "pokus.txt", ios::binary);if( ! f) error();f.write( (char*)&i, sizeof( i));

pole bajtů a jejich počet

Page 61: Objektově orientované programování

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!

Page 62: Objektově orientované programování

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

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;

Šablony

Definice šablony funkce

Typový parametr T nahrazuje skutečný

typmísto typename lze

class

int max( int a, int b) double max( double a, double b)

Page 63: Objektově orientované programování

template<typename T> class Guma{private: int size; T* array;public: const int default_size = 10; Guma( int _size = default_size) { size = _size; array = new T[size]; }; ~Guma() { delete array; } T& operator[] (int n);};

int main(){ Guma<int> ip(5); ip[3] = 999;

Šablony tříd - definice

přetížený operator[]

size: 5

array:

?

3

????

4210

instance šablony třídy

definice proměnné

pole neznámého typu

Page 64: Objektově orientované programování

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];}

Šablony metod, instance šablon

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];

instancešablony

třídydefinice

typu

pk[i] je typu Krabice&

definice

šablony

metody

Page 65: Objektově orientované programování

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 << "]";

STL – Standard Template Library

obousměrný seznam

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

přidání prvku zepředu ...

zezadu ... zepředuiterátor seznamu

průchod seznamem

přístup k datům přes iterátor – operator*

Page 66: Objektově orientované programování

STL – kontejnery

Sekvenční kontejnery Asociativní kontejneryuspořádané setříděné

Page 67: Objektově orientované programování

STL – kontejnery

Sekvenční kontejnery deque – dvoustranná fronta [dek]

umožňuje v konst. čase přidávat na začátek i konec implementace typicky pomocí polí adaptéry (specializované použití i rozhraní): stack, queue, priority_queue

vector – pole (gumové) přístup k prvku v konstantním čase jako vector se chová i string a standardní pole (T x[]) string – chytré řetězce

=, +, += a mnoho dalších operací a metod list – dvousměrný seznam

implementace: spojový seznam umožňuje v konstantním čase přidávat prvky na libovolné místo

Asociativní kontejnery map, multimap – zobrazení, asociativní pole, slovník, mapa

uspořádaná struktura indexovaná libovolným typem, pair: klíč, hodnota) set, multiset – množina, multimnožina

každý prvek nejvýše jednou / vícekrát

Page 68: Objektově orientované programování

STL – iterátory a metody kontejnerů

kontejner<T>::iterator iterátor příslušného kontejneruT& iterator::operator* přístup k prvku přes iterátor

begin(), end() iterátor na začátek / za(!) konec kontejnerupush_front(), push_back() přidání prvku na začátek / konecpop_front(), pop_back() odebrání prvku ze začátku / konce – nevrací hodnotu!front(), back() prvek na začátku / koncioperator[], at() přímý přístup k prvkuinsert(iterator,T) vložení prvku na místo určené iterátoremsize(), empty(), clear() velikost / neprázdost / smazání kontejneru

push(), pop(), top() přidání / odebrání / prvek na vrcholu zásobníku

Page 69: Objektově orientované programování

STL – použití iterátorů

vector<int> pole;vector<int>::iterator p;for( p = pole.begin(); p != pole.end(); p++) cout << "[" << *p << "]";

vytvoření celočíselného vectoru

pole

p je iterátor do vector<int>

pole.begin() vrátí iterátor na začátek

pole

pole.end() vrátí iterátor

za konec pole

p++ (overl.) zařídí, že p

bude ukazovat na další prvek

jestli p už

nedosáhl konce

*p (overl.) vrátí hodnotu prvku na nějž

ukazuje iterátor

Page 70: Objektově orientované programování

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;

STL – použití asociativního pole

pair<string,string> iterator::operator*

ti->first ≡ (*ti).first

ts:

pair:

string second

string first

operator [] (const string&)

vyhledání podle first

Page 71: Objektově orientované programování

STL – algoritmy

Inicializacefill Fills a sequence with an initial valuefill_n Fills n positions with an initial valuecopy Copies a sequence into another sequencecopy_backward Copies a sequence into another sequencegenerate Initializes a sequence using a generatorgenerate_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 conditionadjacent_find Finds consecutive duplicate elementsfind_first_of Finds one member of a seq. in another seq.

find_end Finds the last occurr. of a sub-seq. in a seq.

search Matches a sub-sequence within a sequence

max_element Finds the maximum value in a sequence

min_element Finds the minimum value in a sequence

mismatch Finds first mismatch in parallel sequences

Mazáníremove Removes elements that match conditionunique Removes all but first of duplicate values

Ostatnífor_each Applies a function to each element

Transformace prvkůreverse Reverses the elements in a sequencereplace Replaces specific values with new valuereplace_if Replaces elements matching predicaterotate Rotates elements in a sequence around a point

next_permutation Generates permutations in sequenceprev_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 elementsmake_heap Converts a range into a heap

Skalární výpočtycount Counts number of elements matching value

count_if Counts elements matching predicateaccumulate Reduces sequence to a scalar valueequal Checks two sequences for equalitylexicographical_compare Compares two sequences

Výpočty generující sekvencetransform Transforms each elementpartial_sum Generates sequence of partial sumsadjacent_difference Gen. sequence of adjacent differences

+ mnoho dalších

Page 72: Objektově orientované programování

STL – použití algoritmů

void tiskni( int x) { cout << " [" << x << "]"; }

vector<int> pole;vector<int>::iterator b, e, p;

generate( b = pole.begin(), e = pole.end(), rand);for_each( b, e, tiskni);p = max_element( b, e);sort( p, e);unique( p, e);for_each( b, pole.end(), tiskni);

vlastní funkce pro jeden prvek

pro každý prvek se

zavolá funkce

vyplní se náhodnými čísly

odstraní duplicity

setřídí část pole od max. prvku do

konce

najde max. prvek

vrátí iterátor!! pozor – může

zneplatnit iterátor e

Page 73: Objektově orientované programování

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'

Page 74: Objektově orientované programování

string

Compare strings ==,!=,<,<=, >,>=,compare()

Concatenates strings +

Replaces characters replace()

Changes the number of characters (deletes or appends chars at the end)

resize()

Removes all characters (makes it empty)

clear()

Deletes characters erase()

Inserts characters insert()

Append characters +=,append(),push_back()

Swaps values between two strings swap()

Assign a new value =, assign()

Destroys a string destructor

Create or copy a string constructors

Returns the allocator get_allocator()

Provide reverse iterator support rbegin(), rend()

Provide normal iterator support begin(), end()

Search for a certain substring or character

find functions

Returns a certain substring substr()

Returns the value as character array data()

Returns the value as C-string c_str()

Copies or writes the contents to a C-string

copy()

Writes the value to a stream <<

Read the value from a stream >>, getline()

Access a character [], at()

Returns the number of characters that can held without be reallocation

capacity()

Returns whether the string is empty empty()

Returns the maximum possible number of characters

max_size()

Return the number of characters size(), length()

Page 75: Objektově orientované programování

Výjimky

Motivace: co dělat, když (knihovní) funkce zjistí chybu?nedostatek paměti, nelze otevřít soubor, nulový ukazatel, ...

Vypsat zprávu na 'obrazovku' a skončit FUJ! Nikdy!

Nastavit do globální funkce příznak chyby problém s více vlákny, nutnost neustále testovat

Vrátit 'divnou' hodnotu takhle funguje většina knihovních funkcí C nepříliš praktické, testování každé funkce, vnořené testy divná hodnota nemusí existovat

Co chceme: oddělit detekci výjimečné situace od jejího zpracování po výskytu 'chyby' (výjimečné situace) automaticky skočit na

zpracování kulturně po sobě uklidit (volání destruktorů)

Řešení v C++: mechanismus výjimek

Page 76: Objektově orientované programování

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 exceptionpokusný

bloktry blocktry block

handler(y)typ výjimky

standardní metoda třídy runtime_error

řetězec z konstruktoru

Page 77: Objektově orientované programování

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;}

Výjimky - jednoduchý příklad

pokud se nepovede naalokovat, nastane

výjimka

při výjimce se dále nepokračuje, hledá se nejbližší volný handler

nalezený handler

Page 78: Objektově orientované programování

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

Page 79: Objektově orientované programování

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

Page 80: Objektově orientované programování

... 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ě'

Page 81: Objektově orientované programování

Dodelat na priste

Vice slajdu o pretezovani operatoru (i unarni)Vice slajdu o referenciChytre retezce – pocitane odkazy


Recommended