22.01.2015 Views

Seminář C++ - UTEE - Vysoké učení technické v Brně

Seminář C++ - UTEE - Vysoké učení technické v Brně

Seminář C++ - UTEE - Vysoké učení technické v Brně

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

FAKULTA ELEKTROTECHNIKY A KOMUNIKAČNÍCH TECHNOLOGIÍ<br />

VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ<br />

Seminář <strong>C++</strong><br />

Garant předmětu:<br />

Doc.Ing.Pavel Fiala, Ph.D.<br />

Autoři textu:<br />

Doc. Ing. Pavel Fiala, Ph.D.<br />

Ing. Eva Kroutilová, Ph.D.<br />

Ing. Jan Mikulka<br />

Brno 25.2.2009


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Obsah<br />

1 ÚVOD ................................................................................................................................4<br />

1.1 ZÁKLADNÍ POJMY A UJEDNÁNÍ.....................................................................................5<br />

1.2 VLASTNOSTI C/<strong>C++</strong> ....................................................................................................6<br />

1.3 ZÁSADY, SMĚRNICE ANSI...........................................................................................8<br />

1.4 OBJEKTOVĚ ORIENTOVANÉ PROGRAMOVÁNÍ ...............................................................9<br />

1.5 PROGRAM- OPERAČNÍ SYSTÉM.....................................................................................9<br />

1.6 SESTAVENÍ PROGRAMU................................................................................................9<br />

1.7 ZÁKLADNÍ PRVKY ZÁPISU BLOKOVÉHO SCHÉMATU ...................................................12<br />

1.8 ALGORITMY...............................................................................................................13<br />

1.9 KONTROLNÍ OTÁZKY .................................................................................................19<br />

1.10 ÚKOL.........................................................................................................................19<br />

2 NĚKTERÉ ROZDÍLY C A <strong>C++</strong>...................................................................................20<br />

2.1 KLÍČOVÁ SLOVA <strong>C++</strong> ................................................................................................21<br />

2.2 ÚKOL.........................................................................................................................22<br />

3 TŘÍDY .............................................................................................................................23<br />

3.1 DATOVÉ SLOŽKY .......................................................................................................24<br />

3.2 ČLENSKÉ FUNKCE- METODY ......................................................................................25<br />

3.3 UKAZATEL THIS ........................................................................................................30<br />

3.4 AGREGÁTY ................................................................................................................30<br />

3.5 OBLASTI PLATNOSTI A DOSAŽITELNOSTI IDENTIFIKÁTORŮ ........................................31<br />

3.6 PROSTORY JMEN ........................................................................................................31<br />

3.7 PAMĚŤOVÉ TŘÍDY ......................................................................................................32<br />

3.8 KONTROLNÍ OTÁZKY .................................................................................................33<br />

3.9 ÚKOLY ......................................................................................................................33<br />

4 OBJEKTY .......................................................................................................................34<br />

4.1 PŘIŘAZOVÁNÍ OBJEKTŮ .............................................................................................34<br />

4.2 PŘEDÁVÁNÍ OBJEKTŮ FUNKCÍM .................................................................................34<br />

4.3 VRÁCENÍ OBJEKTŮ FUNKCEMI ...................................................................................35<br />

4.4 ÚKOL.........................................................................................................................36<br />

5 OPERÁTORY.................................................................................................................37<br />

5.1 PŘEHLED OPERÁTORŮ................................................................................................37<br />

5.2 POPIS A UŽITÍ OPERÁTORŮ .........................................................................................39<br />

5.3 PŘETĚŽOVÁNÍ OPERÁTORŮ ........................................................................................42<br />

5.4 ÚKOL.........................................................................................................................44<br />

6 DĚDIČNOST ..................................................................................................................45<br />

6.1 SYNTAKTICKÝ ZÁPIS..................................................................................................45<br />

6.2 PŘÍSTUPY V DĚDIČNOSTI............................................................................................46<br />

6.3 ÚKOL.........................................................................................................................48<br />

7 POLYMORFISMUS ......................................................................................................49<br />

7.1 ÚKOL.........................................................................................................................49<br />

8 PŘETĚŽOVÁNÍ FUNKCÍ ............................................................................................50<br />

8.1 PŘETĚŽOVÁNÍ KONSTRUKTORŮ .................................................................................50<br />

str. 2


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

8.2 ANACHRONISMUS PŘETĚŽOVÁNÍ ...............................................................................52<br />

8.3 PŘETĚŽOVÁNÍ A NEJEDNOZNAČNOST.........................................................................52<br />

8.4 ÚKOL.........................................................................................................................53<br />

9 ŠABLONY FUNKCÍ A TŘÍD .......................................................................................54<br />

9.1 PARAMETRY ŠABLON.................................................................................................54<br />

9.2 ŠABLONY FUNKCÍ ......................................................................................................54<br />

9.3 ŠABLONY OBJEKTOVÝCH TYPŮ..................................................................................55<br />

9.4 ÚKOL.........................................................................................................................56<br />

10 OBSLUHA VÝJIMEK...............................................................................................57<br />

10.1 ÚKOL.........................................................................................................................59<br />

11 ZÁVĚR ........................................................................................................................60<br />

11.1 LITERATURA..............................................................................................................60<br />

str. 3


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

1 Úvod<br />

Předmět Seminář <strong>C++</strong> je vyučován v letním semestru 2. ročníku bakalářského studia<br />

VUT v Brně, FEKT a předpokládá úspěšné absolvování kurzů Počítače a programování 1<br />

a Počítače a programování 2. Volně navazuje na znalosti získané v těchto kurzech a bude<br />

také využívat prostředí Borland <strong>C++</strong> Builder 6.0.<br />

Kurz si klade za cíl rozšířit základní znalosti jazyka C a doplnit o prvky <strong>C++</strong> . Usiluje<br />

o hlubší poznatky a dovednosti cestou praktických zkušeností, které se získají při sestavování<br />

zadaných programů a jejich odlaďování. Je volena forma semináře s připravenými<br />

neřešenými úkoly, při jejichž realizace pod odborným dohledem a vedením si student bude<br />

dále budovat své programátorské schopnosti. Student se tak velmi efektivně a individuálně<br />

rozvíjí, může dosáhnout dobrých výsledků a získat návyky vedoucí k samostatnému<br />

vzdělávání nejen v oblastech tvorby počítačových programů.<br />

Kurzy Počítače a programování 1 a Počítače a programování 2 byly z velké části<br />

zaměřeny na koncepci událostmi řízeného programování, jeho úvod a procvičení s prvky API.<br />

Seminář <strong>C++</strong> naopak bude budovat klasicky orientované programování - tvorbu funkcí,<br />

zařazených do událostmi řízeného programu. Bude dbát na efektivní využití prvků C/<strong>C++</strong>, pro<br />

tvorbu krátkých a rychlých programů se všemi výhodami jazyka <strong>C++</strong>. V čase přiděleném pro<br />

seminář nelze sice zvládnout problematiku <strong>C++</strong> na špičkové úrovni, ale je zde prostor pro<br />

vybudování základních programátorských návyků a potlačení programátorských zlozvyků.<br />

V programování platí mnoho základních pravidel, jak se stát programátorem. Mezi tři velmi<br />

důležité patří: „nejdříve mysli, pak piš“, „programátorem se stáváme podle počtu dobře<br />

napsaných vlastních (nikoliv opsaných) programů“ a „programátor se pozná podle algoritmu“.<br />

V kurzu se budeme snažit psát programy nezávislé na platformě, na které se budou<br />

provozovat.<br />

Následující text lze označit za osnovu pravidel <strong>C++</strong>, mnohdy „děravou“. Existuje<br />

několik přístupů k výuce programování. Jedna cesta je založena na doručení veškerých<br />

informací na stůl budoucího programátora, kterému stačí už jen začít programovat. Jiná cesta,<br />

která je dle mého soudu bližší skutečnému životu, je získání pouze základních informací<br />

o programovacím jazyku s ukázkou základních typů příkladů. Programátor si sám musí najít<br />

doplňující informace a tak i řešení programované úlohy. Samozřejmostí jsou studentovy<br />

velmi dobré základny algoritmizace. Cestou druhou se orientuje kurz Seminář <strong>C++</strong>.<br />

V textu budeme střídat tato různá písma:<br />

Times New Roman – zvýraznění částí textů (zejména různé názvy)<br />

Courier – části zdrojových textů<br />

Courier – klíčová slova ve zdrojovém textu<br />

Arial<br />

– název diskového souboru nebo adresáře<br />

Arial<br />

– nově zaváděný termín<br />

str. 4


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

1.1 Základní pojmy a ujednání<br />

Programátoři mezi sebou komunikují specifickým jazykem. Abychom tomuto jazyku<br />

porozuměli, seznámíme se nyní společně s pojmy, s nimiž se budeme setkávat.<br />

Abstrakce pojem je převážně používán v souvislosti s implementací tříd. Označuje<br />

skutečnost, kdy třída je chápána jako vnějšími vlastnostmi popsaný objekt a není dále<br />

vysvětlena jeho vnitřní funkce.<br />

Členská funkce je taková, která patří k jedné třídě. Zahrnuje chování objektů této třídy.<br />

Někdy se mluví o metodě.<br />

Dědění je označení vztahů v hierarchii objektů a tříd. Třídy lze uspořádat do hierarchie<br />

a předávat (přebírat)-dědit tak vlastnosti (základních, rodičovských) tříd. Odvozená třída<br />

přebírá jak datové složky, tak metody. Odvozená třída představuje specializovanější objekt.<br />

Základní vlastností objektově orientovaného programování (OOP) je možnost zastoupení<br />

předka dědicem.<br />

Funkce je část kódu, která definuje odezvu programu na určitou událost. Funkce je<br />

posloupnost příkazů, které jsou při jejím volání postupně vykonávány.<br />

Instance je vzor, příklad, případ typu třídy. Někdy se označuje jako objekt.<br />

Objekt je označení jak reálných typů, tak i objektových typů (instancí). Označení objekt<br />

se používá i pro oblast paměti, se kterou lze manipulovat (proměnná, konstanta, funkce, atd.)<br />

Objektově orientovaný je nazýván přístup, při kterém jsou problémy řešeny jako<br />

zavádění, určování a implementace objektů ve formě tříd a práce s nimi. Jádro práce<br />

programátora spočívá v implementaci tříd do řešení problému a volání metod<br />

z implementovaných tříd. Knihovny tříd se dají opakovaně používat, tím se práce zjednoduší<br />

a OOP se přiblíží k lidskému způsobu uvažování.<br />

Polymorfismus (mnohotvarost) je vlastnost, která umožňuje, aby jediný název byl<br />

použit jak pro více souvisejících a technicky odlišných účelů, tak pro rozdílné metody. Uvnitř<br />

třídy procesů je volba procesu dána typem dat.<br />

Předefinování je proces, při kterém se mění vlastnosti zděděné funkce v odvozené<br />

třídě. Důvodem je úprava funkce tak, aby reagovala správně na požadované volání.<br />

Předefinování je základním klíčem a krokem k realizaci polymorfismu.<br />

Přetěžování funkcí je pojem, kdy několik funkcí má stejné jméno, které překladač<br />

vzájemně rozlišuje podle počtu a složení a typů parametrů. Někdy se tento termín používá<br />

v souvislosti s hierarchií tříd a polymorfismem, ale je přesnější mluvíme-li o předefinování.<br />

Přetěžování operátorů je schopnost rozšířit operátory o uživatelem definované typy.<br />

Překladač určuje, kterou operaci chceme provést.<br />

Rozhraní je prostředek pro výměnu informací mezi funkcemi, třídami, moduly, atd.<br />

Rozhraní funkce určují její parametry, rozhraní třídy datové složky nebo členské funkce.<br />

Skrývání informací a implementace je tendence vývoje překladače. Jde o to, aby<br />

programátor o funkci nemusel vědět příliš mnoho informací, ale mohl ji přesto používat.<br />

Třída jako datový typ je představitelem skupiny objektů z řešeného problému se<br />

společnými vlastnostmi a způsobem chování.<br />

Událost popisuje přesně definovanou situaci nebo akci, na níž má program reagovat.<br />

Událostí je např. kliknutí na tlačítko v okně (OnClick), stisknutí klávesy na klávesnici<br />

str. 5


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

(onKeyDown) či otočení kolečkem mezi tlačítky myši (OnMouseWheel). Pracujeme-li<br />

v Borland <strong>C++</strong> Builder, píšeme tzv. událostmi řízený program. Pro události, na které má náš<br />

program reagovat, sestavujeme obslužné funkce. Vznik události odpovídající funkci<br />

automaticky vyvolá.<br />

Zapouzdření je mechanismus, kdy objekty v programu lze popsat svými vlastnostmi<br />

(data) a chováním (metoda), je spojen dohromady kód a data v jednom objektu. To lze<br />

shrnout do třídy, která objekt reprezentuje. Tím se přistupuje k objektu z vnějšku jako<br />

k souhrnu vlastností a reakcí.<br />

1.2 Vlastnosti C/<strong>C++</strong><br />

V dnešní době je jazyk C a <strong>C++</strong> považován za jeden ze základních programovacích<br />

jazyků. Umožňuje velmi jednoduše sestavit program, aplikaci pro graficky orientovaný<br />

systém, dokáže pracovat s daty, přistupovat k hardwaru, generuje rychlý kompaktní kód, který<br />

zůstává přenositelný mezi velkou skupinou počítačů. Má vlastnosti vyššího programovacího<br />

jazyka.<br />

Při vyvíjení <strong>C++</strong> byla zachována kompatibilita s jazykem C, nikoliv striktně. V <strong>C++</strong><br />

jsou některé konstrukce nepřípustné, i když v C jsou běžné. Vyskytují se i shodné tvary<br />

konstrukce v obou jazycích, ale jsou odlišně interpretovány. Základním krokem od C k <strong>C++</strong><br />

bylo zavedení tříd, což otevřelo cestu do světa objektového programování. Úspěch zavedení<br />

a používání obou jazyků spočíval v tom, že přechod od C k <strong>C++</strong> byl snazší díky téměř úplné<br />

kompatibilitě obou variant jazyka. Další výhodou <strong>C++</strong> je jeho použití bez nutného využívání<br />

objektově orientovaného programování.<br />

Řekněme si několik slov o koncepci jazyka C. Jazyk C byl navržen pro systémové<br />

programování v Unixu. Byl pomocným prostředkem pro velmi rychlé a snadné sestavení<br />

spustitelného kódu. Jeho rysy lze bodově označit<br />

• malé bohatství prvků<br />

• velká rychlost programů<br />

• připravenost pro modulární programování<br />

• dobrá přenositelnost<br />

• blízkost k operačnímu systému<br />

Jazyk <strong>C++</strong> postupem času reagoval na změny v hodnotách ve světě programování.<br />

Strojový čas je levnější, práce a čas programátora dražší. Charakteristika <strong>C++</strong> je vyjádřena<br />

v několika bodech<br />

• jednoduchý a spolehlivý<br />

• vysoký stupeň opakovaného použití (modulární stavba)<br />

• snadná údržba<br />

• srozumitelný (až intuitivně)<br />

Požadavek srozumitelnosti a přenositelnosti vedl ke vzniku rozsáhlého množství<br />

knihovních funkcí, tím se přenositelnost zhoršila. Různí výrobci překladačů přidávali svá<br />

vylepšení, a tak se vytvořila paleta modifikací jazyka. Bylo nutné situaci vyřešit a vytvořit<br />

závazný standard. To provedla komise založená v roce 1983 Americkým národním institutem<br />

pro standardizaci (American National Standard Institute - ANSI), která v roce 1989 přijala<br />

str. 6


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

koncept jazyka ANSI. Od ní jej převzala i organizace ISO (International Standards<br />

Organization).<br />

Nabízí se otázka, co je to objektově orientované programování Odpověď není snadná.<br />

Jde především o způsob myšlení, uvažování a organizace vztahů objektů. Pokusíme se tento<br />

pojem rozvést. Programování lze chápat jako organizování závislostí, vztahů a výkonných<br />

operací s předpokladem, že budou provedeny za předem dohodnutých podmínek (syntaxe<br />

jazyka, algoritmus programovaného problému, … ). První programy byly tvořeny nastavením<br />

přepínačů, později pomocí děrných štítků, pásek - jazyka symbolických instrukcí. Po roce<br />

1955 se vývoj zaměřil na první překladače jazyka. Začaly se tvořit lineární dlouhé programy<br />

s často se opakujícími algoritmy. Proto následoval posun směrem ke strukturovanému<br />

programování – definované struktury, podprogramy s rekurzivním voláním. Díky omezením<br />

v rozsahu bylo nutné vyvinout kvalitativně lepší přístup než je strukturované programování<br />

a tím bylo objektově orientované programování (OOP). OOP se inspirovalo dobrými znaky<br />

strukturovaného programování a doplnilo je novými koncepty. Základním rysem OOP je<br />

rozložení problému na základní prvky (komponenty) a ty jsou používány jako samostatné<br />

a nezávislé objekty. Obsahují své vlastní instrukce a data používané uvnitř objektu. Tím se<br />

sníží složitost celého programu a je možné tvořit rozsáhlejší algoritmy. Charakteristickými<br />

vlastnostmi OOP je<br />

• Zapouzdření (encapsulation)<br />

• Polymorfismus-mnohotvarost (polymorphism)<br />

• Dědičnost (inheritance).<br />

Zapouzdření je způsob chování objektu. Kód i data objektu jsou chráněny před zásahem<br />

z venčí. Při spojení kódu a dat vzniká objekt. Uvnitř objektu jak kód, tak data, funkce mohou<br />

být neveřejná (private) nebo veřejná (public). Neveřejná data jsou dostupná jen v daném<br />

objektu nebo jeho části. Pro uživatele se objekt jeví jako proměnná. Pokaždé, když si<br />

definujeme nový typ objektu, vytváří se nový typ dat. Uveďme příklady na deklaracích tříd.<br />

Příklad 1<br />

class BasicClass<br />

{ int a; // neveřejné vzhledem k BasicClass<br />

public:<br />

double add(double x, double y);<br />

};<br />

nebo jiná třída<br />

Příklad 2<br />

// veřejné k BasicClass<br />

class camera<br />

{ char *vyrobce, *typ; // znaky popsane hodnotami<br />

int PocetObjektivu, PocetOptickychElementu;<br />

Boolean digital, zrcadlovka, profi;<br />

public:<br />

void zapnout();<br />

// způsob chováni<br />

void manual();<br />

// způsob chováni<br />

void program();<br />

// způsob chováni<br />

void snimek();<br />

// způsob chováni<br />

void vyvolani();<br />

// způsob chováni<br />

void prohlizeni(); // způsob chováni<br />

void vypnout();<br />

// způsob chováni<br />

};<br />

str. 7


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Polymorfismus je vlastnost jazyka, překladače, která umožňuje použití stejných názvů<br />

pro různě účely (objekty, funkce,…). Tam, kde polymorfismus nebyl povolen, hrozilo<br />

nebezpečí shody názvů interních i uživatelských a následná kolize programu. Polymorfismus<br />

dovoluje vytvářet standardní rozhraní k příslušným procesům. Někdy se polymorfismem<br />

označuje přetěžování funkcí a operátorů. Původní význam byl zaveden pro virtuální funkce.<br />

Ukážeme si jednoduchý příklad deklarace třídy:<br />

Příklad 3<br />

class TrA<br />

{ public:<br />

void Fce(int);<br />

};<br />

class TrB<br />

{ public:<br />

void Fce(char*);<br />

};<br />

void main()<br />

{ TrA prvni;<br />

TrB druha;<br />

prvni.Fce(3);<br />

druha.Fce("pokus");<br />

}<br />

Dědičnost je proces, ve kterém jeden objekt může získat vlastnosti jiného procesu.<br />

Přesněji řečeno, může zdědit původní vlastnosti a doplnit je o vlastní, charakteristické pouze<br />

pro něj. Tato vlastnost OOP podporuje hierarchické uspořádání programu na místo plošného<br />

nebo lineárního uspořádání, což zkracuje kód a zpřehledňuje jej.<br />

1.3 Zásady, směrnice ANSI<br />

Příčinou úspěšného zavedení jazyka C a <strong>C++</strong> do počítačového světa bylo vytvoření<br />

(komisí ANSI) a respektování několika zásad, které lze shrnout do následujících bodů:<br />

• Důležitý je existující kód, ne existující implementace (v překladači). Kód by měl být<br />

zachován za cenu změny implementace překladače.<br />

• Kód napsaný v jazyce C je přenositelný. ANSI kód nabízí programátorům možnost<br />

přenositelnosti programu v jazyce C ANSI mezi různými operačními systémy.<br />

• Kód napsaný v C může být nepřenositelný. Existuje možnost vytvořit programový kód,<br />

který je vázán na určitý hardware a tím není přenositelný na ostatní.<br />

• Ohlašovat odlišnosti od standardu. Neměla by nastat varianta, kdy překlad jednoho<br />

textu programu bude na různých překladačích interpretován různě. Pokud ano, musí být<br />

na tyto odlišnosti od ANSI programátor upozorněn.<br />

• Standard je dohodou mezi implementátorem a programátorem. Zásada by měla vést<br />

k respektování jak u výrobce překladače, tak u programátora.<br />

Nyní máme definovány základní pojmy, stanovena pravidla a můžeme se věnovat<br />

procvičování jednotlivých částí. Uvedeme si i příklady některých základních rozdílů mezi C,<br />

<strong>C++</strong> a nové směry v <strong>C++</strong>.<br />

str. 8


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

1.4 Objektově orientované programování<br />

Objektově orientované programování se není pouze rozšíření znalostí C na některé nové<br />

prvky <strong>C++</strong>. (použití nového cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

DOS MS Windows 1.0, 2.0, 3.0, 3.1, 95<br />

Obr.2 Schéma sestavení programů pro platformy<br />

Obr.3 Schéma toku událostí v systému událostmi řízeném<br />

Pro korektní vložení vlastního zdrojového programu do existující šablony je několik přístupů.<br />

Pokusím se vybrané postupy vysvětlit. První, známý z kurzu Počítače a programování 2 je<br />

vložení zdrojového kódu jako textu přímo do vygenerované „šablony“. Pak se program<br />

přeloží a je spustitelný. Tato metoda je poněkud nepružná a „nemotorná“. Musíme mít editor<br />

textu, správný formát atd.<br />

str. 10


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Příklad 4<br />

#pragma hdrstop<br />

#include "Unit1.h"<br />

//------------------------------------------------------------------<br />

#pragma package(smart_init)<br />

#pragma resource "*.dfm"<br />

TForm1 *Form1;<br />

//------------------------------------------------------------------<br />

__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)<br />

{}<br />

int mojeExtFunkce(void)<br />

{/* text vlozene funkce*/}<br />

//------------------------------------------------------------------<br />

void __fastcall TForm1::fPokus(TObject *Sender)<br />

{}<br />

//------------------------------------------------------------------<br />

Účelnější, ale možná ne tak „vizuálně “ podporované řešení, je vložení textu naší funkce<br />

pomocí hlavičkového souboru. Neobsahuje-li funkce složité vazby na API a objekty<br />

uživatelského rozhraní, je to velmi rychlý způsob. K psaní programu nepotřebuji žádný<br />

složitý programový nástroj. Stačí tužka, papír a na počítači dostupný textový editor. Text by<br />

vypadal si takto:<br />

Příklad 5<br />

#pragma hdrstop<br />

#include "Unit1.h"<br />

#include "mojeExtFunkce.h"<br />

//------------------------------------------------------------------<br />

#pragma package(smart_init)<br />

#pragma resource "*.dfm"<br />

TForm1 *Form1;<br />

//------------------------------------------------------------------<br />

__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)<br />

{}<br />

//------------------------------------------------------------------<br />

void __fastcall TForm1::fPokus(TObject *Sender)<br />

{}<br />

//------------------------------------------------------------------<br />

Soubor mojeExtFunkce.h v adresáři, kde jsou umístěny soubory projektu má tento obsah<br />

int mojeExtFunkce(void)<br />

{<br />

/* text vložené funkce*/<br />

}<br />

Pro úplnost ještě snad chybí uvést schéma sestavování programu v současných překladačích.<br />

Na obr.4 je to velmi zjednodušeně naznačeno. Některé typy souborů nemusí být použity,<br />

tvůrci překladačů vytvářejí jiné soubory, dočasné soubory jsou mazány. Postup překladu je<br />

v zásadě zachován, směřuje odshora dolů.<br />

str. 11


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Soubory na disku<br />

Uživatelské soubory<br />

Systémové soubory<br />

*.h *.c *.h<br />

Předzpracování, kontrola chyb<br />

*.i<br />

Překlad, kontrola chyb<br />

*.dll<br />

*.obj<br />

*.obj *.obj *.lib<br />

*.lib<br />

*.dll<br />

Sestavení<br />

*.exe<br />

*.com<br />

*.exe<br />

DDE<br />

Obr.4 Postup sestavení spustitelného souboru<br />

1.7 Základní prvky zápisu blokového schématu<br />

Pro srozumitelný zápis algoritmů programů si uvedeme základní značky objevující<br />

v blokových schématech.<br />

Značka pro začátek, konec<br />

začátek,<br />

konec<br />

Značka pro načtení (vstup), výstup<br />

Vstup A, Výstup A<br />

Značka pro skok<br />

Značka pro předepsaný postup:<br />

skok na<br />

A=B, A=A+1, A=A*B<br />

Značka pro funkci, podprogram<br />

Značka pro cyklus<br />

cyklus I = 1, .., N<br />

Značka pro rozhodnutí<br />

a, nebo ∧ , ∨ negace A A AB, A=B, A≠B, A≥B, A≤B<br />

str. 12


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

1.8 Algoritmy<br />

Při řešení programátorské úlohy se naskytne zpravidla více přístupů a postupů. Jeden<br />

postup je z nich třeba vybrat a formulovat jej pomocí vývojového diagramu. Pro výběr se<br />

musí stanovit vhodná kritéria, aby bylo možné rozhodnout, který postup je „lepší“ a který<br />

„horší“. Co to je „lepší“ a „horší“ Kritéria pro posuzování kvality algoritmu jsou subjektivní<br />

a objektivní. Problematika kritérií je velmi rozsáhlá, ale pro účely tohoto textu se budeme<br />

držet nutných pojmů a praktických důsledků bez uvedení odvození a důkazů a budeme se<br />

zabývat především základní objektivními kritérii hodnocení algoritmu, která jsou:<br />

1. rychlost algoritmu (výpočtu)<br />

2. paměťová náročnost – operační i externí paměť<br />

3. stabilita algoritmu<br />

První dvě uvedená kritéria jsou významná hlediska posouzení algoritmů a velmi často<br />

stojí při hodnocení proti sobě. Algoritmy bývají takové, že jeden z nich je pomalejší, ale<br />

využívá malou operační paměť, zatímco druhý je rychlejší, ale má vysoké nároky na paměť.<br />

Často je to způsobeno tím, že pro zrychlení algoritmu je použita další pomocná proměnná<br />

nebo množina proměnných. Ty jsou uchovány v operační paměti a zvětšují nároky na paměť<br />

za cenu zrychlení výpočtu. Pro volbu paměťové náročnosti a rychlosti neexistuje obecné<br />

řešení. Vždy záleží na požadavcích, které jsou kladeny na program. Samozřejmě první dvě<br />

kritéria jsou závislá i na použitém technickém vybavení (hardwaru). Jako příklad lze uvést<br />

úlohu vyhledání telefonního čísla v seznamu. Jedním z postupů je tzv. sekvenční vyhledávání.<br />

Začneme procházet seznam od začátku až do nalezení hledaného čísla. Ve skutečnosti jsou<br />

jména v seznamu seřazena podle abecedy. Postup při vyhledávání je podle srovnání<br />

rostoucích n-tic písmen jména. Např. pokud hledáme jméno Novák, první n-tice je N, dále je<br />

hledána druhá n-tice No, atd.<br />

Stabilita algoritmu závisí jak na vstupních údajích programu, tak na zvolené metodě<br />

algoritmu. Doba výpočtu i paměťové nároky bývají také závislé na vstupních údajích.<br />

Program většinou řeší celou řadu podobných problémů, které se liší právě zadávanými<br />

vstupními údaji. Trvání výpočtu i paměťové nároky však často neovlivňují konkrétní zadané<br />

hodnoty, jen velikost vstupních dat. Prakticky je jedno, zda vyhledávám jedno telefonní číslo<br />

v telefonním seznamu s 3000 položkami nebo vyhledávám naměřenou teplotu s 3000 údaji. Je<br />

ale rozdíl, pokud vyhledávám telefonní číslo v seznamu Znojma a Brna. Potom bude<br />

algoritmus mít rozdílnou dobu trvání.<br />

Paměťová náročnost u algoritmů se uvádí v jednotkách jakými jsou bit nebo bajt. Bit je<br />

jednotka, která může být buď ve stavu logické jednotky nebo ve stavu logické nuly. Bajt je<br />

jednotka (slovo), která je složena z několika bitů. Počet bitů v bajtu je dán mnoha kritérii.<br />

Jsou obvykle používány 8, 16, (24), 32, 64, 128, … bitová slova.<br />

Časová náročnost se udává v souvislosti s použitým typem procesoru, velikostí RAM<br />

a její rychlosti, konfiguraci základní desky, typem a výrobcem operačního systému. Udává se<br />

buď jako doba pro nejhorší případ složitosti algoritmu se vstupními daty velikosti N nebo jako<br />

průměrný případ výpočtu z N vstupních dat.<br />

Algoritmy se porovnávají v jejich časové náročnosti a je rozhodnuto, který z nich je<br />

rychlejší. Stává se, že vstupní data a jejich rozsah nejsou specifikovány. Potom nelze stanovit<br />

časovou náročnost. Postupuje se tak, že se zvolí pro rozsah dat velké číslo N a provede se<br />

srovnání algoritmů s uvedením podmínek. Jde o asymptotickou časovou náročnost, tj. časová<br />

náročnost lepšího algoritmu roste pomaleji s rostoucími hodnotami N. Časovou náročnost lze<br />

popsat typem funkce a jejím řádem. Rozeznáváme základní, polynomiální a exponenciální<br />

funkce. Následuje ukázka zadání a vypracování algoritmů základních až triviálních úloh.<br />

str. 13


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Úloha 1 Sestavte a nakreslete diagram algoritmu pro nalezení minimálního čísla z řady N<br />

zadaných. Nechť je výsledek zobrazen na výstupním zařízení.<br />

Začátek<br />

čti N<br />

A=1e99<br />

I=1,..,N<br />

čti číslo X<br />

vypiš MinimumA<br />

-<br />

X


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Úloha 3. Sestavte a nakreslete diagram algoritmu pro nalezení součtu čísel z množiny A<br />

a množiny B . Prvky množiny A i B jsou celá čísla, počet prvků množiny A je N a množiny B<br />

je M. Nechť je výsledek zobrazen na výstupním zařízení.<br />

Začátek<br />

čti N, M<br />

celá A(N), celá B(M)<br />

A(1)= .., A(N)=…<br />

B(1)= .., B(M)=…<br />

SOUCET=0<br />

J=1,..,M<br />

-<br />

B(J) ≠0<br />

+<br />

SOUCET= SOUCET+B(J)<br />

-<br />

I=1,..,N<br />

A(I)≠0<br />

+<br />

vypiš Součet prvků<br />

množinyA a B,<br />

SOUCET<br />

Konec<br />

SOUCET= SOUCET+A(I)<br />

Úloha 4 Sestavte a nakreslete diagram algoritmu pro nalezení součinu čísel z množiny A<br />

a množiny B . Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N a množiny<br />

B je M. Platí, že M=N. Nechť je výsledek zobrazen na výstupním zařízení.<br />

Začátek<br />

čti N, M<br />

reálná A(N), reálná B(M)<br />

A(1)= .., A(N)=…<br />

B(1)= .., B(M)=…<br />

SOUCIN=1<br />

M≠N<br />

+<br />

Konec<br />

-<br />

J=1,..,M<br />

vypiš Součin prvků<br />

množinyA a B,<br />

SOUCIN<br />

B(J) ≠0 ∧<br />

A(J) ≠0<br />

+<br />

-<br />

SOUCIN A a B je<br />

roven 0<br />

SOUCIN= SOUCIN+A(J)*B(J)<br />

str. 15


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Úloha 5 Sestavte a nakreslete diagram algoritmu pro porovnání obsahu množiny A a množiny<br />

B . Prvky množiny A i B jsou celá čísla, počet prvků množiny A je N a množiny B je M. Pokud<br />

množiny mají společný prvek (číslo) zobrazte je na výstupním zařízení.<br />

Začátek<br />

čti N, M<br />

X=N<br />

celá A(N), celá B(M), celá C(X)<br />

A(1)= .., A(N)=…B(1)= .., B(M)=…<br />

Spolecna=0, K=0<br />

-<br />

M>N<br />

+<br />

X=M<br />

I=1,..,N<br />

J=1,..,M<br />

Spolecna = 0<br />

-<br />

+<br />

-<br />

B(J)=A(I)<br />

+<br />

Počet společných prvků K<br />

Společné prvky C(1,..,K)<br />

K=K+1<br />

C(K)= A(I)<br />

Spolecna=1<br />

Konec<br />

Úloha 6 Sestavte a nakreslete diagram algoritmu pro průnik C obsahu množiny A a množiny<br />

B . Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N a množiny B je M.<br />

Množinu C zobrazte na výstupním zařízení.<br />

Začátek<br />

čti N, M<br />

X=N<br />

reálná A(N), reálná B(M), reálná C(X)<br />

A(1)= .., A(N)=…B(1)= .., B(M)=…<br />

Prunik=0, K=0<br />

-<br />

M>N<br />

+<br />

X=M<br />

I=1,..,N<br />

J=1,..,M<br />

Prunik = 0<br />

-<br />

+<br />

-<br />

B(J)=A(I)<br />

+<br />

Počet společných prvků K<br />

C(1,..,K)<br />

K=K+1<br />

C(K)= A(I)<br />

Prunik=1<br />

Konec<br />

str. 16


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Úloha 7 Sestavte a nakreslete diagram algoritmu pro sjednocení C obsahu množiny A<br />

a množiny B. Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N a množiny B<br />

je M. Množinu C zobrazte na výstupním zařízení.<br />

Začátek<br />

čti N, M<br />

reálná A(N), reálná B(M), reálná C(M+N)<br />

A(1)= .., A(N)=…B(1)= .., B(M)=…<br />

Reálná Pomocna=0, celá L=0<br />

I=1,..,N<br />

J=1,..,M<br />

Počet prvků L<br />

C(1,..,L)<br />

-<br />

B(J)≠A(I)<br />

+<br />

Konec<br />

Pomocna= A(I)<br />

L=L+1<br />

C(L)=Pomocna<br />

K=1,..,M+N<br />

+ -<br />

C(K)=Pomocna<br />

Úloha 8 Sestavte a nakreslete diagram algoritmu pro zjištění, zda zadané číslo N je prvočíslo.<br />

Začátek<br />

Začátek<br />

čti N<br />

Prvocislo= 1 reálné A, reálné B<br />

I=2,..,celé(√N)<br />

+<br />

Prvocislo=1<br />

A=celé(N/I)<br />

B=N/I<br />

-<br />

-<br />

+<br />

A=B<br />

Prvocislo= 0 N není prvočíslo<br />

N je prvočíslo<br />

Konec<br />

čti N, M<br />

reálná A(N), reálná B(M), reálná C(M+N)<br />

A(1)= .., A(N)=…B(1)= .., B(M)=…<br />

Reálná Pomocna=0, celá L=0<br />

-<br />

I=1,..,N<br />

J=1,..,M<br />

B(J)≠A(I)<br />

L=L+1<br />

C(L)=Pomocna<br />

+<br />

Pomocna= A(I)<br />

K=1,..,M+N<br />

Počet prvků L<br />

C(1,..,L)<br />

+ -<br />

C(K)=Pomocna<br />

Konec<br />

str. 17


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Úloha 9 Sestavte a nakreslete diagram algoritmu pro výpočet funkce 5 555 .<br />

Začátek<br />

reálná A(40), reálná D<br />

A(1)=1.0<br />

I=1,..,555<br />

D=0.0<br />

J=1,..,39<br />

I=39,..,1<br />

Výpis A(I)<br />

A(J)= 5*A(J)+D<br />

D=celé číslo (A(J)/10 10 )<br />

A(J)=A(J)-D*10 10<br />

Konec<br />

Úloha 10 Sestavte a nakreslete diagram algoritmu pro součet matic A a B. Prvky množiny A i<br />

B jsou reálná čísla, počet prvků množiny A je N×N a množiny B je M×M. Množinu C zobrazte<br />

na výstupním zařízení.<br />

Začátek<br />

čti N, M<br />

reálná A(M,N), reálná B(M,N), reálná C(M,N)<br />

A(1,1)= .., A(1,N)=…B(1,1)= .., B(1,N)=…<br />

C(1,..,M,1,..,N)=0.0<br />

I=1,..,N<br />

J=1,..,M<br />

Výstup matice C(M,M)<br />

C(I,J)= C(I,J)+A(I,J)+B(I,J)<br />

Konec<br />

Úloha 11 Sestavte a nakreslete diagram algoritmu pro součin matice A a vektoru B. Prvky<br />

množiny A i B jsou reálná čísla, počet prvků množiny A je N×N a množiny B je M. Množinu C<br />

zobrazte na výstupním zařízení.<br />

Začátek<br />

čti N, M<br />

reálná A(M,N), reálná B(N), reálná C(N)<br />

A(1,1)= .., A(1,N)=…B(1)= .., B(M)=…<br />

C(1,..,N)=0.0<br />

J=1,..,N<br />

I=1,..,M<br />

C(J)= C(J)+A(I,J)*B(I)<br />

Výstup sloupcové matice<br />

C(M)<br />

Konec<br />

str. 18


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Úloha 12 Sestavte a nakreslete diagram algoritmu pro součin matic A a B. Prvky množiny A i<br />

B jsou reálná čísla, počet prvků množiny A je N×N a množiny B je M×M. Množinu C zobrazte<br />

na výstupním zařízení.<br />

Začátek<br />

čti N, M<br />

reálná A(M,N), reálná B(N,M), reálná C(N,N)<br />

A(1,1)= .., A(M,N)=…B(1,1)= .., B(N,M)=…<br />

C(1,..,N, 1,..,N)=0.0<br />

K=1,..,N<br />

I=1,..,N<br />

J=1,..,M<br />

Výstup matice C(N,N)<br />

C(I,K)= C(I,K)+A(J,I)*B(K,J)<br />

Konec<br />

1.9 Kontrolní otázky<br />

1. Vysvětlete, co je to abstrakce a jak se využívá<br />

2. Vysvětlete, co je to polymorfismus a kde se s ním setkáme<br />

3. Vysvětlete, co je to přetěžování funkcí a operátorů, jak ovlivní naše možnosti při<br />

programování<br />

4. Jak byste charakterizovali vlastnosti jazyka <strong>C++</strong><br />

5. Jaké jsou základní vlastnosti a rysy objektově orientovaného programování<br />

6. Pro uvedené příklady algoritmů napište v <strong>C++</strong> jednoduché funkce.<br />

1.10 Úkol<br />

1. Sestavte jednoduchou funkci, odlaďte ji a spojte s jednoduchým programem v Borland<br />

Builderu.<br />

str. 19


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

2 Některé rozdíly C a <strong>C++</strong><br />

Mezi jazyky C a <strong>C++</strong> i přes jejich podobnost existují drobné rozdíly. Předpokládejme,<br />

že čtenář má základní znalosti z programování v C a orientuje se v problematice. Pokusím se<br />

pomocí tabulky ukázat některé rozdíly v obou jazycích.<br />

OBSAH C <strong>C++</strong> VÝZNAM<br />

prototyp funkce Fce() int Fce(void)<br />

prototyp funkce<br />

Fce()<br />

prototyp funkce nepovinný povinný<br />

deklarace funkce<br />

s návratem hodnoty<br />

deklarace lokálních<br />

proměnných<br />

typ proměnné<br />

nemusí vracet (nebo vrací<br />

int)<br />

začátek bloku před<br />

výkonnými proměnnými<br />

musí vrátit vždy<br />

kdekoliv<br />

bool, klíčová slova<br />

true, false<br />

int Fce()<br />

int Fce(void)<br />

Pro úplnost a upřesnění vysvětlíme některé často používané pojmy, které se mohou<br />

nesprávně interpretovat. Mezi první dva patří deklarace a definice.<br />

Deklarace seznamuje počítač s názvem proměnné, funkce, třídy šablony nebo datového typu.<br />

Deklarací stanovíme její typ, paměťovou třídu a viditelnost jejího identifikátoru. Určíme také<br />

typ vracené hodnoty a počet, pořadí a typy parametrů a eventuálně jejich implicitní hodnoty.<br />

Deklarace v <strong>C++</strong> začíná klíčovým slovem extern.a neobsahuje inicializaci. Popis statické<br />

datové složky v deklaraci třídy je jen deklarace, nikoliv definice. Mezi deklarace patří<br />

typedef, using.<br />

Definice nejen objekt popisuje, ale přikazuje i překladači jeho zřízení. Proměnné, funkce<br />

a další součásti programu dostupné v celém těle programu mohou mít více deklarací. Statické<br />

proměnné a funkce mohou mít v kterémkoliv z modulů jinou definici. Definice proměnné<br />

v <strong>C++</strong> buď neobsahuje klíčové slovo extern nebo obsahuje inicializaci. Definice funkce<br />

obsahuje její tělo. Statické datové složky tříd musíme definovat za deklarací třídy (mimo tělo<br />

funkce).<br />

Ukážeme si rozdíl mezi deklarací a definicí na jednoduchém příkladě, který provede součet<br />

dvou celých čísel<br />

Příklad 6<br />

int secti(int a, int b);<br />

// deklarace funkce<br />

int secti(int a, int b)<br />

// definice funkce<br />

{ return(a+b);} // závorky zde nemusí být<br />

void main(void)<br />

{ int vysledek = secti(5,10); // volání fce<br />

str. 20


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

printf("Soucet je %d.",vysledek);<br />

}<br />

Z kurzů Počítače a programování 1 a Počítače a programování 2 jsou známy základní<br />

informace o datových typech, výčtových typech, jedno a vícerozměrných polích, řetězcích,<br />

strukturách, bitových polích, uniích, ukazatelích, dynamických proměnných, práci s ukazateli.<br />

Pokračovali bychom dále v prohloubení znalostí z oblasti tříd.<br />

2.1 Klíčová slova <strong>C++</strong><br />

NÁZEV VÝZNAM POZNÁMKA<br />

asm<br />

auto<br />

bool<br />

break<br />

case<br />

catch<br />

char<br />

class<br />

const<br />

const_cast<br />

continue<br />

default<br />

delete<br />

do<br />

double<br />

dynamic_cast<br />

else<br />

enum<br />

explicit<br />

extern<br />

false<br />

float<br />

for<br />

friend<br />

goto<br />

if<br />

inline<br />

int<br />

long<br />

mutable<br />

namespace<br />

new<br />

operator<br />

private<br />

protected<br />

public<br />

register<br />

reinterpret_cast<br />

str. 21


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

return<br />

short<br />

NÁZEV VÝZNAM POZNÁMKA<br />

signed<br />

sizeof<br />

static<br />

satic_cast<br />

struct<br />

switch<br />

teplate<br />

this<br />

throw<br />

true<br />

try<br />

typedef<br />

typeid<br />

typename<br />

union<br />

unsigne<br />

using<br />

virtual<br />

void<br />

volatile<br />

wchar_t<br />

while<br />

2.2 Úkol<br />

1. Sestavte jednoduchou funkci, vyzkoušejte změny mezi syntaxí C a <strong>C++</strong>, odlaďte ji<br />

a spojte s jednoduchým programem v Borland Builderu.<br />

str. 22


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

3 Třídy<br />

Třídy slouží ke spojení (zapouzdření) dat a funkcí do jednoho (nového) typu. Umožňují<br />

předepisovat různá oprávnění k přístupu k jednotlivým prvkům. Třídy mají díky dědičnosti<br />

hierarchické uspořádání. Deklarace může být zapsána:<br />

klíč třída[:seznam_předků]<br />

{<br />

deklarace_prvků<br />

}[případ1,případ2,...];<br />

kde je klíč class, struct nebo union, v <strong>C++</strong> struktury a unie představují pouze zvláštní<br />

případy tříd, Třída - identifikátor třídy, :seznam_předků - seznam identifikátorů tříd,<br />

jejichž vlastnosti má nová třída zdědit, deklarace_prvků - v těle třídy se deklarují její<br />

složky. Přístup k prvkům mohou upravovat specifikátory přístupových práv (public,<br />

protected, private). případ1 - zde se mohou definovat případy (instance),<br />

ukazatele na případy, pole případů. Uveďme si konkrétní příklad.<br />

Příklad 7<br />

class Priklad<br />

{ int Hodnota; // soukromé (private)<br />

public:<br />

// veřejné (public)<br />

Priklad(){Hodnota=1;}; // konstruktor<br />

protected:<br />

// chráněné (protected)<br />

int treti(){ return Hodnota;};<br />

private:<br />

// soukromé (private)<br />

int Posledni();<br />

};<br />

• Specifikace přístupových práv platí pro všechny složky, které jsou zapsány za ní, až do<br />

další specifikace.<br />

• Specifikace přístupových práv se mohou v deklaraci třídy vyskytovat vícekrát.<br />

• Složky třídy na začátku deklarace před první specifikací přístupových práv jsou<br />

automaticky považovány za<br />

⋅ soukromé (private) ve třídách definovaných pomocí klíčového slova class.<br />

⋅ veřejné (public) ve třídách definovaných jako struct a union.<br />

• Specifikace přístupových práv se nevztahují na spřátelené funkce.<br />

• Používání tříd v OOP se řídí jistými pravidly. Rozlišují se vlastnosti a způsob chování<br />

objektů. Společné objekty lze zahrnout do jedné třídy. Například:<br />

Příklad 8<br />

class Mesto<br />

{ /* znaky popsané hodnotami*/<br />

char *Nazev;<br />

int PocetObyvatel;<br />

boolean MestskaDoprava, Silnice, Dalnice, Metro, Letiste,<br />

Divadlo, park, Obchod, Skola;<br />

public: /*způsob chování*/<br />

str. 23


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

};<br />

void Ubytovani();<br />

void Zamestnani();<br />

void Odpocinek();<br />

void Sport();<br />

void Doprava();<br />

Pokud podle dané třídy deklarujeme proměnnou – případ (instance), musí být datovým<br />

složkám přidělena hodnota. Potom deklarovaná proměnná představuje jediné identické město<br />

např. Brno.<br />

Mluvili jsme o zapouzdření dat a členských funkcí. Pro práci s třídami se může ještě<br />

přidat další pojem - skrývání dat. Je to stav, kdy programátor používá členské funkce třídy<br />

a nestará se, jak program vykoná zamýšlené operace na připojeném HW. Například v třídě<br />

Mesto pro případ Brno bychom spustili funkci Brno.Doprava(); a tím by program podle<br />

těla funkce řídil dopravu v celém městě Brně. Programátora ale nezatěžuje, jak se přes<br />

rozhraní počítače provádí spouštění systémů pro řízení křižovatek, tramvajové a autobusové<br />

dopravy.<br />

Dalším pojmem je uzavřenost. Tím se myslí takové nadefinování třídy, které je úplné<br />

(neobsahuje zbytečně mnoho nebo málo údajů) a je právě vhodná k provádění operací podle<br />

jejího chování.<br />

3.1 Datové složky<br />

Třídy mají datové složky. Každý případ třídy dostane k dispozici paměť pro datové<br />

složky. Při jejich tvorbě dojde k jejich inicializaci (přiřazením hodnot), které provede<br />

konstruktor. Se zánikem proměnné datové složky zanikají, což provádí destruktor.<br />

Datové složky mohou být deklarovány jako:<br />

• veřejně přístupné (public)<br />

• chráněné (protected)<br />

• soukromé (private)<br />

• statické (static)<br />

Statické složky<br />

⋅<br />

⋅<br />

⋅<br />

⋅<br />

⋅<br />

⋅<br />

⋅<br />

jsou společné pro všechny případy (instance)<br />

vznikají při spuštění programu- jde o globální proměnnou, zapsanou ve třídě<br />

nemohou být deklarovány jako auto, register, extern<br />

jejich zápis v definici třídy je jen deklarace<br />

definice se provede vně třídy<br />

se mohou používat prostřednictvím jména třídy (JmenoTridy::StatickyPrvek)<br />

nelze je deklarovat pomocí const<br />

Složky deklarované jako<br />

⋅<br />

⋅<br />

⋅<br />

const - musí se inicializovat, ale pak je dále nelze měnit (konstanty)<br />

mutable - lze je měnit i když je případ deklarován jako const<br />

volatile - ty mohou neočekávaně (asynchronně) měnit svůj obsah, překladač<br />

neoptimalizuje (zkracuje, upravuje) operace s touto proměnnou<br />

str. 24


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Třída nemůže obsahovat jako datovou složku sebe sama. Ale může obsahovat ukazatel nebo<br />

reference na nedefinovanou třídu (i na sebe sama).<br />

Příklad 9<br />

class test<br />

{ int PocetObyvatel;<br />

class test a;<br />

class test* b;<br />

class test &c;<br />

};<br />

//Chyba<br />

//Dobře<br />

//Dobře<br />

Lokální třídy<br />

Třídy, které jsou definovány v příkazové části funkce, se označují jako lokální. Jsou<br />

omezeny a všechny metody se musí definovat v těle třídy.<br />

Vnořené třídy<br />

Příklad 10<br />

Uvnitř třídy se může jako složka deklarovat datový typ. Tedy i třídu.<br />

int i;<br />

class Vnejsi<br />

{ static int n;<br />

public:<br />

int i;<br />

static float f;<br />

class vnitrni<br />

{<br />

void test(Vnejsi &glob)<br />

{<br />

i=5;<br />

// Má být glob.i<br />

f=1;<br />

// Správně<br />

::i=1;<br />

// Odkaz na globální i<br />

glob.i=-1; // Správně, i z třídy global<br />

n=5;<br />

// Chyba<br />

};<br />

};<br />

};<br />

class priklad* b;<br />

class priklad &c;<br />

//Dobře<br />

//Dobře<br />

3.2 Členské funkce- metody<br />

• Mohou být deklarovány jako public, protected, private.<br />

• Pokud jsou definované jako static, pak pracují pouze s datovými složkami static.<br />

str. 25


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

• Metody mohou pracovat s objekty typu const. Metody mohou být deklarovány jako<br />

virtual, inline (ukázkou jednoduché inline funkce, která zjistí, zda 10 je sudé<br />

číslo je Příklad 11).<br />

• Mohou být přetěžovány pouze členskými funkcemi stejné třídy.<br />

• Mají přístup ke všem prvkům své třídy bez ohledu na přístupová práva.<br />

• Jsou jediným prostředkem s funkcemi typu friend, jak získat přístup k soukromým<br />

prvkům- private.<br />

• Metody mohou být deklarovány jak uvnitř, tak vně deklarace třídy.<br />

Příklad 11<br />

#include <br />

using namespace std;<br />

inline int funkce1(int x) { return !(x%2);} // vrací true, je-li<br />

// argument funkce sudý<br />

int main()<br />

{ if(funkce1 (10)) cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Přístup k prvkům tříd<br />

Velmi osvědčené je navržení tříd tak, že jejich prvky jsou typu private. Potom je mohou<br />

používat jen metody dané třídy. Vně třídy k nim mají přístup pouze členské funkce.<br />

Přístup zevnitř třídy<br />

Příklad 14<br />

class test<br />

{ private:<br />

int n1, n2;<br />

int fun1() {return n1*n2;}<br />

public:<br />

void fun2(int j)<br />

{<br />

n1=j+1;<br />

n2=fun1();<br />

}<br />

};<br />

test z;<br />

// z je případem třídy test<br />

z.fun2(222);<br />

// Změna z.n1 a z.n2<br />

Přístup z vnějšku třídy<br />

Pokud se pracuje s prvky třídy a přistupuje se k nim z vnějšku třídy, musí se uvést případ, pro<br />

který chceme složky měnit. Přístup je pomocí případu třídy a operátoru tečka- jméno složky<br />

nebo ukazatel a připojíme jméno složky pomocí operátoru přiřazení (->).<br />

• Přístup přes případ je filtrován specifikátory public, protected, private.<br />

Příklad 15<br />

class test<br />

{ int n1; // Private (soukromé)<br />

int fun1();<br />

// Private (soukromé)<br />

public:<br />

int n2;<br />

// Public (veřejné)<br />

int fun2();<br />

// Public (veřejné)<br />

};<br />

void main()<br />

{ test z, *PokusD; //Případy třídy<br />

int i;<br />

i=z.n1;<br />

//Chyba,n1 je private-nelze přistoupit zvenčí<br />

i=PokusD->fun1(); //Chyba,fun1 je private–nelze přistoupit zvenčí<br />

i=z.n2;<br />

// Správně, n2 je public<br />

i=PokusD->fun2(); // Správně, fun2 je public<br />

return 0;<br />

}<br />

• Pravidla přístupu se obejdou přes přátele - klíčové slovo friend. Zápis je<br />

friend ProtoypFunkce;<br />

friend class JmenoTridy;<br />

str. 27


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Aby se tyto přístupy podařilo provést, musí být funkci předán ukazatel na případ, reference na<br />

případ nebo přímo případ třídy.<br />

Příklad 16<br />

class test<br />

{ int n1;<br />

friend void fun1(test&);<br />

};<br />

void fun1(test& objekt)<br />

{ int a;<br />

a=objekt.n1;<br />

}<br />

void main()<br />

{ class test T;<br />

fun1(T);<br />

return 0;<br />

}<br />

• Třída určuje funkce, které jsou spřátelené a chrání tím data před nekontrolovaným<br />

použitím.<br />

• Jako spřátelené funkce mohou být deklarovány i metody jiných objektových typů.<br />

• Mimo deklarace spřátelených funkcí se může deklarovat celá třída jako spřátelená.<br />

Přetěžování a předefinování<br />

Pokud se v odvozené třídě deklaruje nevirtuální metoda se stejným jménem jako v bázové<br />

třídě, zastíní deklarace v odvozené třídě deklaraci z bázové třídy. To je stav, kdy zděděná<br />

metoda nebude přímo dostupná i když je odlišná. Pro její použití se musí použít jméno<br />

předka.<br />

Příklad 17<br />

class Zaklad<br />

{ public:<br />

void fun1(int);<br />

};<br />

class Odvozena:Zaklad<br />

{ public:<br />

void fun1(char*);<br />

};<br />

void main()<br />

{ Odvozena odv; // Případ třídy Odvozena<br />

odv.fun1(3);<br />

// Chyba<br />

odv.Zaklad::fun1(3); // Správně<br />

return 0;<br />

}<br />

Zvláštní metody<br />

Mezi zvláštní metody patří vytvoření případu – konstruktor, který má několik pravidel<br />

použití. Základní jsou:<br />

• Konstruktor má vždy stejné jméno jako jeho třída<br />

str. 28


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

• Konstruktor nemá žádnou návratovou hodnotu<br />

• Pokud konstruktor nedeklarujeme, překladač v třídě sám vytvoří veřejně přístupný<br />

konstruktor bez parametrů<br />

• Pokud explicitně deklarujeme jakýkoliv konstruktor, nebude překladač žádný další<br />

vytvářet<br />

• Konstruktory mohou být přetěžovány<br />

• Konstruktory se nedědí, konstruktor potomka automaticky volá konstruktory<br />

bezprostředních prvků<br />

• Nelze deklarovat ukazatel na konstruktor<br />

• Konstruktory, které mají právě jeden parametr, mohou provádět konverzi na typ své<br />

třídy<br />

• Konstruktor se volá při dynamické alokaci případu pomocí operátoru new.<br />

Příklad 18<br />

class test<br />

{ int privat;<br />

public:<br />

test(int i){privat=1;}<br />

explicit test(float g){privat=(int)g;}<br />

};<br />

//Konstruktor<br />

void main()<br />

{ test pripad(100);<br />

test pripad2=100;<br />

test pripad3(3.2);<br />

test pripad4=3.2;<br />

return 0;<br />

}<br />

//Implicitní konverze<br />

//Chyba: explicitní konverze parametru není<br />

Inicializační část konstruktoru<br />

Inicializační část je určena k inicializaci datových složek třídy. Má tvar<br />

identifikátor_složky (hodnota)<br />

identifikátor_složky (SeznamParametruKonstruktoru)<br />

identifikátor_třídy (SeznamParametruKonstruktoru)<br />

Příklad 19<br />

class test<br />

{ int i;<br />

public:<br />

test(int j):i(j){}<br />

};<br />

//do i je uložena hodnota parametru<br />

class testB<br />

{ test T;<br />

int x;<br />

public:<br />

testB(int y):x(y-1), a(10){fce1();}<br />

};<br />

str. 29


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Zrušení případu - destruktor<br />

Destruktory se volají automaticky při zániku případu (například delete - zrušení<br />

dynamické proměnné).<br />

• Destruktor nemá žádnou návratovou hodnotu<br />

• Pokud v třídě nedeklarujeme explicitně destruktor, vytvoří si překladač veřejně<br />

přístupný standardní destruktor<br />

• Destruktor se nedědí<br />

• Nelze definovat ukazatel na destruktor<br />

• Destruktor nemá žádné parametry<br />

• Destruktory mohou být i virtuální<br />

• Destruktory můžeme explicitně volat.<br />

3.3 Ukazatel this<br />

Každý případ má svou kopii nestatických datových složek třídy. Metody jsou v paměti<br />

uloženy jen jednou a používají je všechny případy třídy společně. Je-li v nestatické metodě<br />

odkaz na nestatickou datovou složku jejím identifikátorem, je to odkaz na aktuální případ<br />

vytvořené třídy.<br />

Ukazatel na aktuální případ<br />

Na aktuální případ se můžeme odkázat klíčovým slovem this. Ukazatel this se předává<br />

jako skrytý parametr, programátor jej tedy nemusí deklarovat. Jednoduchý příklad ukazuje<br />

použití ukazatele.<br />

Příklad 20<br />

class complex<br />

{ double Re, Im;<br />

public:<br />

complex(double _Re, double _Im):Re(_Re), Im(_Im){}<br />

double Real();<br />

double Imag();<br />

};<br />

double complex::Real(){return Re;}<br />

double complex::Imag(){return Im;}<br />

V metodě Real() je příkaz return Re vlastně return this->Re.<br />

3.4 Agregáty<br />

Agregáty jsou struktury, které nemají<br />

• žádný uživatelem definovaný konstruktor<br />

• nestatické prvky, deklarované jako private nebo protected<br />

• nestatické reference<br />

• nestatické konstantní složky (const)<br />

• ve svojí deklaraci uveden předek<br />

str. 30


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

• bázové třídy<br />

• virtuální členské funkce.<br />

Agregáty je možné inicializovat výčtem hodnot ve složených závorkách.<br />

Příklad 21<br />

class test<br />

{ public:<br />

struct Struktura<br />

{ int i;<br />

float p;<br />

}Str;<br />

void fun1();<br />

};<br />

test T = {3,3.1415926};<br />

3.5 Oblasti platnosti a dosažitelnosti identifikátorů<br />

Blok<br />

Funkce<br />

Prototyp<br />

funkce<br />

Soubor<br />

Třída<br />

Identifikátor deklarovaný v těle funkce je platný v místě jeho deklarace a končí<br />

na konci bloku. Formální parametr funkce je platný na začátku jeho deklarace<br />

a končí na konci těla funkce.<br />

Oblast platnosti se týká pouze návěští pro příkaz skoku.<br />

Oblast platnosti končí s koncem prototypu.<br />

Oblast platnosti se týká globálních identifikátorů (deklarované mimo tělo<br />

funkce). Platnost začíná v místě deklarace a končí na konci souboru.<br />

Oblast platnosti identifikátoru definovaného uvnitř třídy začíná v místě<br />

deklarace, obsahuje celé tělo třídy, těla všech metod, specifikace formálních<br />

parametrů a jejich implicitních hodnot a také inicializační část konstruktorů<br />

i mimo tělo třídy.<br />

Jména deklarovaná uvnitř třídy jsou dostupná i mimo třídu když jsou zapsány<br />

případem (operátor tečka), ukazatelem na případ (operátor ->), někdy<br />

jménem třídy (operátor ::).<br />

3.6 Prostory jmen<br />

Tyto prostory jsou nástroje vhodné pro organizaci identifikátorů v programu, aby<br />

nedošlo k jejich konfliktům v rozsáhlém programu. Deklarace prostoru jmen je<br />

namespace [jmenovka]{deklarace}<br />

• Najde-li překladač druhý prostor jmen se stejnou jmenovkou, bude jej považovat za<br />

rozšíření prostoru.<br />

str. 31


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

• Prostory jmen můžeme deklarovat pouze na úrovni souboru nebo uvnitř jiného<br />

prostoru jmen.<br />

• Deklarujeme-li v daném prostoru jmen třídu, pak její spřátelené funkce (deklarované<br />

uvnitř třídy), patří také do tohoto prostoru jmen.<br />

• Klíčovým slovem using lze zpřístupnit objekt z libovolného prostoru jmen bez<br />

nutnosti opakované deklarace.<br />

using jmenovka :: identifikátor //zpřístupní se daný identifikátor<br />

using namespace jmenovka //zpřístupní se všechny identifikátory<br />

//z daného prostoru<br />

Příklad 22<br />

namespace test<br />

{ int i=1; //test::i<br />

void fun1(int);<br />

struct T<br />

{ int i=2; //test::T::i<br />

};<br />

}<br />

namespace test<br />

// pokračování<br />

{ int i=3; //nepřípustné- opakovaná definice<br />

void fun1(float);<br />

// přetížení<br />

void fun2(float);<br />

// korektní<br />

namespace<br />

// nepojmenovaný prostor<br />

{ int i=4; //test::T::i<br />

};<br />

}<br />

void test::fun1(float x);<br />

// definice vně prostoru<br />

{ return i; // test::i<br />

}<br />

Příklad 23<br />

namespace A<br />

{ int i=1;<br />

}<br />

namespace B<br />

{ int i=2;<br />

using namespace A;<br />

}<br />

void main()<br />

{ i=i+1; // Chyba - není zpřístupněn<br />

A::i=A::i+1;<br />

// Správný zápis<br />

using namespace B;<br />

i=i+6;<br />

// Není jasné o který prostor jde A::i nebo B::i<br />

return 0;<br />

}<br />

3.7 Paměťové třídy<br />

Při deklaraci můžeme ještě zadat pro proměnnou její paměťovou třídu. Paměťová třída<br />

a místo deklarace určují viditelnost a dobu života proměnné.<br />

str. 32


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

• auto proměnné jsou lokální v bloku<br />

• register proměnné jsou automatické proměnné, u kterých požadujeme umístění<br />

do registru procesoru.<br />

• static proměnná je globální a má omezenou viditelnost.<br />

• extern se přiřazuje proměnné nebo funkci z vnějšího přístupu<br />

• mutable povoluje měnit konstantní objekty.<br />

3.8 Kontrolní otázky<br />

1. V čem spočívají výhody tříd<br />

2. Jakou roli v úspoře času a prostoru při programování v <strong>C++</strong> hierarchické členění<br />

objektů<br />

3. Existuje nějaké rozdělení přístupu k prvkům třídy<br />

3.9 Úkoly<br />

1. Sestavte program pro načtení a uložení dat na disk s daty z tabulky jednoduché<br />

aplikace. Využijte maximálně vlastností OOP.<br />

2. Sestavte program pro zadání a řešení soustavy lineárních rovnic Gaussovou eliminační<br />

metodou. Využijte maximálně vlastností OOP.<br />

str. 33


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

4 Objekty<br />

S označením objekt se setkáme v životě i v programovacích jazycích. Tvůrci<br />

programovacího jazyka se snaží pro jeho srozumitelnost a pochopení napodobit vlastnosti<br />

prvků a názvosloví běžné v každodenním životě. Objektem je nazýván jak obraz třídy, tak<br />

i její případ (instance). Někdy se používá název objekt i pro přístupnou část paměti<br />

(konstanta, proměnná, pole proměnných, funkce, ...).<br />

4.1 Přiřazování objektů<br />

Předpokládejme, že objekt je popsán třídou. Příklad ukazuje jednoduchou operaci se dvěmi<br />

objekty. Jde o přiřazení objektu O2 objektu O1. Data obou jsou totožná, ale přitom jsou O1<br />

a O2 objekty oddělené.<br />

Příklad 24<br />

using namespace A;<br />

class test<br />

{ int a,b;<br />

public:<br />

void fun1(int i, int j){a=i;b=j}<br />

void show(){cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

int get_a(){return a;}<br />

};<br />

int kva_a(test x)<br />

// kva_a přebírá argument třídy test<br />

{return x.get_a()* x.get_a(); // Provede se kvadrát argumentu<br />

}<br />

int main()<br />

{ test a(5),b(6); // a a b jsou případem třídy test<br />

cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

};<br />

public:<br />

void show(){cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

5 Operátory<br />

V této části se budeme blíže zabývat vlastnostmi operátorů.<br />

5.1 Přehled operátorů<br />

V následující tabulce je uveden seznam a původní význam operátorů.<br />

OPERÁTOR POPIS POZN.<br />

+ součet operandů (binární)<br />

+ identita (unární)<br />

- rozdíl operandů (binární)<br />

- změna znaménka (unární)<br />

+= součet operandů a přiřazení výsledku levému operandu<br />

-= rozdíl operandů a přiřazení výsledku levému operandu<br />

* aritmetické násobení<br />

* přístup k hodnotě proměnné (ukazatel)<br />

*= aritmetické násobení a přiřazení výsledku levému operandu<br />

/ aritmetický podíl dvou operandů<br />

/= aritmetický podíl dvou operandů výsledek je přiřazen levému<br />

% výsledek po celočíselném dělení<br />

%= výsledek po celočíselném dělení přiřazen levému operandu<br />

! logická negace<br />

not<br />

logická negace<br />

!= logická relace nerovná se<br />

not_eq logická relace nerovná se<br />

&<br />

adresa operandu (unární)<br />

&<br />

konjunkce po bitech (binární)<br />

bitand konjunkce po bitech (binární)<br />

&=<br />

konjunkce po bitech a výsledek přiřadí levému operandu<br />

and_eq konjunkce po bitech a výsledek přiřadí levému operandu<br />

&&<br />

konjunkce- logický součin<br />

and<br />

konjunkce- logický součin<br />

(int).... přetypování na int, lze libovolně použít<br />

dynamic_cas<br />

t<br />

přetypování v rámci dědické hierarchie s dynamickou<br />

kontrolou typů<br />

static_cast změna typů objektů a standardní C/<strong>C++</strong><br />

const_cast změna typů, kdy se předávají nebo odstraňují modifikátory<br />

const a volatile<br />

reinterpret<br />

_cast<br />

nepřenositelné přetypování<br />

, čárka, operátor pro sekvenční vyhodnocování<br />

++ zvýšení hodnoty operandu o jednu<br />

-- snížení hodnoty operandu o jednu<br />

-> přístup ke složce případu (instance) prostřednictvím<br />

ukazatele<br />

str. 37


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

. tečka, přístup ke složce případu prostřednictvím případu<br />

= přiřazení<br />

== logická relace rovno<br />

< logická relace menší než<br />

> logická relace větší než<br />

logická relace větší nebo rovno<br />

>= posunutí bitů doprava a přiřazení výsledku levému operandu<br />

: podmíněný výraz<br />

[] indexování pole<br />

() volání funkce<br />

^<br />

bitová nerovnost XOR<br />

xor<br />

bitová nerovnost XOR<br />

^= bitová nerovnost a přiřazení výsledku levému operandu<br />

xor_eq bitová nerovnost a přiřazení výsledku levému operandu<br />

| logická relace disjunkce – OR po bitech<br />

bitor logická relace disjunkce – OR po bitech<br />

|= logická relace disjunkce po bitech a přiřazení výsledku levému<br />

operandu<br />

or_eq logická relace disjunkce po bitech a přiřazení výsledku levému<br />

operandu<br />

|| logická relace disjunkce - OR<br />

or<br />

logická relace disjunkce - OR<br />

~ doplněk (binární)<br />

compl doplněk (binární)<br />

: inicializace třídy<br />

:: operátor rozsahu, zpřístupnění globálního jména, jména ze tříd<br />

a prostorů jmen<br />

.* přístup k hodnotě třídy s pomocí případu<br />

->* přístup k hodnotě třídy s pomocí ukazatele na případ<br />

sizeof vrací velikost operandu v bytech<br />

typeid dynamické určení typu<br />

new<br />

dynamické přidělení paměti<br />

delete uvolnění dynamicky přidělené paměti<br />

delete[] uvolnění dynamicky přidělené paměti pole<br />

# převod parametru makra na řetězec (preprocesor)<br />

## spojování symbolů (preprocesor)<br />

defined test na přítomnost definovaného makra (preprocesor)<br />

Podle počtu operátorů můžeme operátory klasifikovat na<br />

• unární (+, -,&, *, !, ~, ++, --, sizeof )<br />

• binární (=, +=, - =, *=, /=,


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

by měly být stejného typu. Pokud nejsou, provede se jejich převedení (konverze). Konverze<br />

má svá pravidla, ale ze zkušeností vyplývá, že na ně nelze spoléhat. Mohou způsobit při<br />

přenosu zdrojového kódu a následném překladu nedozírné komplikace, proto dobří<br />

programátoři řádně definují převody již při psaní zdrojového kódu programu. Nebudeme se<br />

dále zabývat pravidly konverze. Následující příklady ukazují některá použití operátorů.<br />

5.2 Popis a užití operátorů<br />

Unární operátory + ,- mění hodnoty operandu. Pro binární operátory +, -, /, * , % platí<br />

známá pravidla. Přiřazovací operátory jsou obdobně používány jako v jazyce C a ostatních<br />

jazycích. V jazyce C jsme se seznámili se složenými operátory.<br />

Příklad 28<br />

void main()<br />

{ int a,b;<br />

a=1;<br />

b=2;<br />

a+=b;<br />

return 0;<br />

}<br />

// ekvivalent a=a+b<br />

Použití relačních a logických operátorů je standardní jako v jazyce C, podobně přístup<br />

k datům je shodný jako v jazyce C. Výjimečně mohou nastat obtíže v přístupech k objektům.<br />

Jednoduché příklady ukazují možnosti použití přístupu.<br />

Příklad 29<br />

struct test<br />

{ char jmeno[100];<br />

int cislo_vyr;<br />

};<br />

void main()<br />

{ test auto;<br />

strcpy(auto.jmeno, ”Jaguar”);<br />

auto.cislo_vyr=51023659874515926;<br />

return 0;<br />

}<br />

Příklad 30<br />

struct test<br />

{ char jmeno[100];<br />

int cislo_vyr;<br />

};<br />

void main()<br />

{ struct test auto;<br />

struct test* p_auto=&auto;<br />

strcpy(p_auto->jmeno, ”Jaguar”);<br />

p_auto->cislo_vyr=51023659874515926;<br />

str. 39


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

return 0;<br />

}<br />

Bitové operátory jsou definovány pouze pro celočíselné typy proměnných. V operandech se<br />

pracuje s jednotlivými bity. Patří sem operace AND, OR, NOT, COMPL. Jako příklad práce<br />

s bitovými operátory lze uvést:<br />

Příklad 31<br />

0110 0001 znak ´a´<br />

&1101 1111 maska<br />

0100 0001 znak ´A´<br />

0100 0001 znak ´A´<br />

|0010 0000 maska<br />

0110 0001 znak ´a´<br />

0001 1001<br />

^0000 1100<br />

0001 0101<br />

Nepoužívané nebo často neznámé jsou operátory new a delete, které slouží k přidělování<br />

a uvolňování dynamické paměti. Nahrazují dříve používané funkce ze skupiny malloc()<br />

a free(). New umožňuje přidělit dynamicky alokovaným objektům počáteční hodnotu.<br />

Delete umožní vytváření dynamicky alokovaných polí. Ukážeme si na několika příkladech<br />

jejich použití.<br />

Příklad 32<br />

#include <br />

using namespace std;<br />

int main()<br />

{ int *p;<br />

p = new int;<br />

// přidělené místo pro typ integer<br />

*p = 1000; //na adresu p se uloží 1000<br />

cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

char te[sizeof(test)];<br />

x_test=new test[10];<br />

x_test=new(te) test;<br />

test * utest = new(nothrow) test(5);<br />

//deklarace třídy<br />

//alokace pole<br />

//konstrukce případu třídy<br />

//nevyvolává výjimky,<br />

//alokuje případ třídy<br />

Objekty vytvořené pomocí new mají neomezenou dobu trvání. Paměťová místa se musí<br />

uvolnit operátorem delete.<br />

Příklad 34<br />

class test *p =new test[10];<br />

delete[] p;<br />

int **xx = new int*;<br />

delete x;<br />

//alokace<br />

//uvolnění paměti<br />

//alokace<br />

//uvolnění paměti<br />

V následující části textu se velmi stručně dotkneme přetypování. Klasické přetypování z C je<br />

asi takovéto:<br />

Příklad 35<br />

int a; //<br />

double b,c;<br />

c=(double) a/b;<br />

Ke komplikovanějšímu přetypování, jako je například přetypování ukazatele, je určen<br />

operátor dynamic_cast. Ukažme si na příkladu jeho použití.<br />

Příklad 36<br />

class zakl<br />

{ public:<br />

virtual void fce();<br />

};<br />

class dcera: public virtual zakl<br />

{ public:<br />

virtual void fce(){}<br />

virtual void gfce(){int a=1;}<br />

};<br />

void pracuj(zakl *ub)<br />

{ dcera* up = dynamic_cast (ub)<br />

if(up) up->gfce();<br />

else return -1;<br />

}void main()<br />

{ zakl X;<br />

dcera Y;<br />

pracuj (&Y); // Správné přetypování, return 1<br />

pracuj (&X); // Chyba přetypování, return -1<br />

}<br />

str. 41


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

5.3 Přetěžování operátorů<br />

Některé operátory (většina) v <strong>C++</strong> lze předefinovat. Přetížené operátory se definují jako<br />

funkce (operátorové funkce). Při práci s operátory se mohou rozdělit do čtyř skupin:<br />

1. Operátory ::, :, ., .*, sizeof, typeid, dynamic_cast,<br />

static_cast, reinterpret_cast, const_cast, defined, #, ##<br />

NELZE PŘETĚŽOVAT.<br />

2. Operátory ->, [], (), =, (typ) lze přetěžovat pouze jako nestatické metody<br />

objektových typů.<br />

3. Ostatní operátory s výjimkou new a delete lze přetěžovat jako nestatické metody<br />

objektových typů.<br />

4. Operátory new a delete lze přetěžovat jako statické metody objektových typů nebo<br />

jako obyčejné funkce.<br />

Přetěžování operátorů má také svá pravidla, například :<br />

• nelze definovat nové operátory<br />

• není přípustné měnit charakteristiky operátorů (počet operandů, prioritu,…)<br />

• nelze měnit definici operátoru pro standardní datové typy<br />

• jméno operátorové funkce se vždy skládá z klíčového slova operator a symbolu<br />

operátoru<br />

• kromě new a delete operátoru není pro žádný z operátorů předepsán typ vrácené<br />

hodnoty<br />

Příklad 37<br />

class complex<br />

// komplexní čísla<br />

{ double re,im;<br />

public:<br />

complex (double r, double i); // konstruktor<br />

complex operator –();<br />

// unární mínus<br />

friend bool operator !(complex&); //logická negace<br />

};<br />

complex complex::operator-() // vrati komplexni cisla<br />

{ return complex (-re, -im); // s opacnym znamenkem<br />

}<br />

complex operator!(complex& c) // pokud je aspon jedna slozka<br />

{ if(c.re || c.im) // nenulova, vrati true<br />

return true;<br />

else<br />

return false;<br />

}<br />

void main()<br />

{ complex c(0,0), d(0,1);<br />

c=-d;<br />

if(!c) test(c);<br />

return 0;<br />

}<br />

// ekvivalent c=d.operator-()<br />

str. 42


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

V následujícím příkladu (Příklad 38) si ukážeme přetížení operátoru ++ vzhledem ke třídě<br />

pretiz. Operátor ++ navyšuje své operandy. Zde ++ modifikuje objekt, nad nímž operuje.<br />

Funkce vrací objekt, který inkrementuje. To umožňuje, aby mohl být inkrementační operator<br />

použit i jako součást většího příkazu (např. o2=++o1;).<br />

Příklad 38<br />

class pretiz<br />

{ int x, y; // hodnoty souřadnic<br />

public:<br />

pretiz() { x=0; y=0; }<br />

pretiz(int i, int j) { x=i; y=j; }<br />

void get_xy(int &i, int &j) { i=x; j=y; }<br />

pretiz operator++();<br />

};<br />

pretiz pretiz::operator++()//Přetížení operátoru ++ pro třídu pretiz<br />

{ x++;<br />

y++;<br />

return *this;<br />

}<br />

int main()<br />

{ pretiz o1(10,10);<br />

int x, y;<br />

++o1;<br />

// inkrementuje objekt<br />

o1.get_xy(x, y);<br />

cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

5.4 Úkol<br />

1. Sestavte program pro změnu editovaných písmen z malé na velkou abecedu<br />

a obráceně.<br />

str. 44


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

6 Dědičnost<br />

Dědičnost je jedním ze základních vlastností a prvků OOP, který umožňuje rychlejší<br />

sestavení struktury vlastností objektů. Původní – bázové třídy slouží jako základ pro nové<br />

– odvozené třídy, potomky nebo dceřiné třídy. Třídy vázané dědičnými vlastnostmi se také<br />

označují jako dědická hierarchie.<br />

Existuje několik forem dědičnosti.<br />

• Jednoduchá – jedna bázová a jedna odvozená.<br />

• Vícenásobná – jeden potomek má více předků.<br />

Odvozená třída dědí vlastnosti předků, bude obsahovat všechny nestatické datové složky<br />

předků, bude používat jejich metody, typy a statické složky podle definovaných práv. Některá<br />

pravidla lze bodově shrnout:<br />

• Kritérium sdílení – odvozené třídy by měly korektně sdílet vlastnosti základní třídy.<br />

• Kritérium nezávislosti – vlastní definice odvozené třídy by neměly ovlivňovat použití<br />

zděděných vlastností.<br />

• Kritérium specializace – je-li odvozená třída speciálním případem základní, použije se<br />

k odvození polymorfismu – virtuálních metod. Speciální případy tříd nejsou rozdílné<br />

úrovně v hierarchii.<br />

• Kritérium jednotnosti – dědičnost by měla zajistit rovnoprávnost tříd – jednotný<br />

způsob implementace.<br />

6.1 Syntaktický zápis<br />

Zápis dědičnosti je podle následujícího tvaru<br />

klíč jméno_třídy:seznam_bázových_tříd<br />

{<br />

složky_třídy<br />

};<br />

kde jsou klíč .... class, struct , jméno_třídy je identifikátor odvozené třídy,<br />

seznam_bázových_tříd je výběr tříd, jejichž vlastnosti má odvozená třída dědit a způsob<br />

dědění. Položka má tvar [virtual][specifikátor_přístupu]jméno_bázové_třídy<br />

, specifikátor_přístupu je jeden z public, protected, private.<br />

Složky_třídy jsou definice odvozených tříd. Jednoduchou ukázkou zápisu dědění tříd je<br />

Příklad 40.<br />

Příklad 40<br />

class zakl<br />

// bázová třída<br />

{ int i;<br />

public:<br />

void nastav_i(int n){i=n;}<br />

int vezmi_i(){return i;}<br />

};<br />

str. 45


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

class odvozena: public zakl // odvozená třída<br />

{ int j; // přidána další proměnná<br />

public:<br />

void nastav_j(int n){j=n;} // přidána další funkce<br />

int nasobeni (){return j*vezmi_i();} //přidáno násobení i*j<br />

};<br />

int main()<br />

{ odvozena o1; // o1 je případ odvozené třídy<br />

o1.nastav_i(10); // nastaví se i=10<br />

o1. nastav_j(4); // nastaví se j=4<br />

cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

Příklad 42<br />

class zakl_x<br />

// bázová třída<br />

{ int fce(); // private<br />

public:<br />

int j;<br />

// public<br />

}; //<br />

class odvozena_x: private zakl_x // odvozená třída<br />

{ int i; // private<br />

public:<br />

using zakl_x::fce; // opět public, změna pomocí using<br />

};<br />

Dědická práva platí u všech složek i metod třídy.<br />

Příklad 43<br />

class zakl_x<br />

// bázová třída<br />

{ int prom_a, prom_b; // private<br />

public:<br />

int sou_a(){return prom_a;};<br />

int sou_b(){return prom_b;};<br />

zakl_x: prom_a(10), prom_b(20) {};<br />

};<br />

class odvozena_x: public zakl_x // odvozená třída<br />

{ int suma; // private<br />

public:<br />

odvozena_x: suma(0){};<br />

int scitej();<br />

{ suma+=prom_a+prom_b;<br />

return suma;<br />

}<br />

};V tomto příkladě zřejmě překladač ohlásí chybu, protože je proveden nekorektní zápis<br />

odvozené třídy. Složky prom_a, prom_b jsou v odvozené třídě nepřístupné. Jsou dvě<br />

možnosti změny. První je, že v základní třídě se změní z private na protected.<br />

Příklad 44<br />

class zakl_x<br />

// bázová třída<br />

{ protected: // smí používat potomek<br />

int prom_a, prom_b; // private<br />

public:<br />

int sou_a(){return prom_a;};<br />

int sou_b(){return prom_b;};<br />

zakl_x: prom_a(10), prom_b(20) {};<br />

};<br />

Druhá metoda je založena na změně přístupových práv.<br />

Příklad 45<br />

class odvozena_x: public zakl_x // odvozená třída<br />

{ int suma; // private<br />

public:<br />

odvozena_x: suma(0){};<br />

int scitej();<br />

str. 47


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

};<br />

{ suma+=sou_a()+sou_b();<br />

return suma;<br />

}<br />

Konstruktory a destruktory tříd se nedědí, ale při tvorbě případu odvozené třídy jsou zděděné<br />

datové složky inicializovány konstruktorem základní třídy.<br />

Příklad 46<br />

class zakl_x<br />

// bázová třída<br />

{ int prom_a; // private<br />

public:<br />

int sou_a(){return prom_a;};<br />

zakl_x(void): prom_a(10) {};<br />

zakl_x(int prom_b): prom_a(prom_b) {};<br />

};<br />

class odvozena_x: public zakl_x // odvozená třída<br />

{ int suma; // private<br />

public:<br />

odvozena_x(void): suma(0){};<br />

odvozena_x(int prom_b, int prom_c): zakl_x(prom_b),<br />

suma(prom_c){};<br />

void scitej(zakl_x& b);<br />

}; V deklaraci konstruktoru odvozena_x(void)<br />

nevoláme konstruktor předka. Překladač použije konstruktor zakl_x(void). V konstruktoru<br />

odvozena_x(int) se volá konstruktor zakl_x(prom_b).<br />

6.3 Úkol<br />

1. Sestavte program pro měřicí ústřednu s okny měřicího zařízení (ručkový měřicí<br />

přístroj, osciloskop) tak, aby byly využity vlastnosti dědičnosti měněné podle<br />

nastavení uživatele.<br />

str. 48


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

7 Polymorfismus<br />

Polymorfismus souvisí s principy dědičnosti. Je to jev, kdy jedna metoda (ekvivalentní<br />

funkce) je v různých třídách svázaných dědičností, implementována rozdílně. Vhodné je<br />

používat dědění pomocí společné bázové třídy. V odvozených třídách jsou metody<br />

předefinovány a pozmění se tak účel metody. Metody, které se mají v odvozených třídách<br />

změnit, se deklarují s klíčovým slovem virtual.<br />

Příklad 47<br />

struct bod_1 {double x,y;};<br />

class kres_obj<br />

// bázová třída<br />

{ protected:<br />

bod_1 ref_bod;<br />

virtual int kresli(); // bude se měnit v odvozených třídách<br />

};<br />

{ //nakreslí se bod v daných souřadnicích<br />

//........<br />

};<br />

class obdelnik: public kres_obj // odvozená třída<br />

{ protected:<br />

bod_1 rohy[4];<br />

virtual int kresli(); // bude se měnit<br />

}; //<br />

{ // nakreslí obdélník o daných rozměrech<br />

//........<br />

};<br />

class kruznice: public kres_obj // odvozená třída<br />

{ protected:<br />

bod_1 stred;<br />

float r;<br />

virtual int kresli(); // bude se měnit (nakreslí kružnici)<br />

}; //<br />

{ //nakreslí kružnici o daných rozměrech<br />

//........<br />

};<br />

7.1 Úkol<br />

1. Sestavte program, který provede v okně vykreslení základních geometrických<br />

obrazců – kružnice, elipsa, čtverec, obdélník, kosočtverec, přímka, trojúhelník,....,<br />

(ukázka struktury programu viz Příklad 47).<br />

str. 49


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

8 Přetěžování funkcí<br />

O přetěžování funkcí jsme se již krátce zmínili v předcházejících kapitolách. Nyní se<br />

ještě k tomuto tématu vrátíme.<br />

8.1 Přetěžování konstruktorů<br />

Pro snazší programování a nezatěžování schopností programátora jsou zaváděny<br />

všechny systémy přetěžování. Patří mezi ně i přetěžování konstruktorů. Mimo jiné pomáhá<br />

přetěžování konstruktorů k mnohotvárnosti používání polí, tvorbě kopírovacích konstruktorů.<br />

Při zavádění tříd můžeme, ale nemusíme vytvářet vlastní konstruktory.<br />

Příklad 48<br />

class test<br />

{ int i;<br />

public:<br />

};<br />

test(){i=0}<br />

test(int n){i=n} //s inicializátorem<br />

int getx() {return i};<br />

// přetížení konstruktoru dvojí způsobem<br />

//bez inicializátoru<br />

int main()<br />

{ test o1(10); // deklarace s počáteční hodnotou<br />

test o2;<br />

// deklarace bez inicializátoru<br />

cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

};<br />

test(){i=0}<br />

test(int n){i=n}<br />

int getx() {return i};<br />

//bez inicializátoru<br />

//inicializátor<br />

int main()<br />

{ test o1[10]; // deklarace pole bez inicializátorů<br />

test o2[3]={1,2,3}; // deklarace s inicializátory<br />

return 0;<br />

};<br />

Přetěžováním se dosáhne toho, že programátor si pohodlně může vybrat libovolný typ<br />

inicializace objektu. Při přetěžování se může použít prvek – standardní argument. Je to<br />

způsob předávání parametrů při volání funkci, které je zkráceným zápisem přetěžování<br />

funkce. Zadání standardního argumentu může vypadat například takto:<br />

void test_f (int a=0, int b=0);<br />

Nyní funkce může být volána třemi způsoby:<br />

1. test_f (); //a,b=0<br />

2. test_f (15); //a=15,b=0<br />

3. test_f (1,56); //a=1, b=56<br />

Důležitým konstruktorem je tzv. kopírovací konstruktor. Ten se volá při definici<br />

instance, která má jako inicializátor jinou instanci téže třídy nebo v případě vytváření<br />

dočasných instancí, např. v přiřazení A = B + C. Nejprve je nutné definovat dva druhy<br />

kopírování instancí. Prvním typem je plytké kopírování, kdy přiřazením instancí A = B pouze<br />

zkopírujeme atributy (obsahy) datového prostoru zdrojové instance. Tato metoda selhává<br />

v případě, kdy se v datovém prostoru instance objeví ukazatel do místa v paměti. Pouhým<br />

přiřazením A = B totiž oba ukazatele těchto dvou instancí ukazují na stejné místo v paměti.<br />

Tomu zabráníme kopírováním celých dat (ne pouhých adres) – tzv. hlubokým kopírováním.<br />

Definujeme tedy kopírovací konstruktor – metoda určující pravidla kopírování dat z jedné<br />

instance do druhé.<br />

Příklad 50<br />

class komplex<br />

{<br />

int *Re, *Im; // ukazatel na realnou a imag. část kompl. čísla<br />

public:<br />

komplex(int Re, int Im)<br />

{<br />

// konstruktor se dvěma parametry<br />

// nastaví reálnou část na x a imaginární na y<br />

this->Re = new int(Re);<br />

this->Im = new int(Im);<br />

}<br />

komplex(const komplex &src)<br />

{<br />

// kopírovací konstruktor<br />

// zkopiruje hodnotu realné a imaginární části<br />

str. 51


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

};<br />

}<br />

this->Re = new int(*src.Re);<br />

this->Im = new int(*src.Im);<br />

Na tomto příkladu je vidět definice kopírovacího konstruktoru, který se stará o kopírování dat<br />

a ne adres v datovém prostoru instance. Nyní můžeme vytvořit instanci třídy komplex takto:<br />

komplex A(1,2);<br />

komplex B(A);<br />

Komplexní číslo A bude ve tvaru 1+2i a komplexní číslo B také, protože díky kopírovacímu<br />

konstruktoru dojde ke kopii dat z dynamicky alokovaných proměnných. Dále můžeme psát:<br />

A = B + C;<br />

Přetížením operátoru + můžeme sečíst dvě komplexní čísla. Zde vznikne kopírovacím<br />

konstruktorem dočasná instance (X), která obsahuje jejich součet. Přetížením operátoru = dále<br />

můžeme data z dočasné instance kopírovat do výsledné instance A.<br />

8.2 Anachronismus přetěžování<br />

V době vzniku <strong>C++</strong> bylo pro přetěžování vymezeno klíčové slovo overload. Nyní je<br />

zastaralé a není používáno, ale je možné se s ním setkat ve starších zdrojových textech. Jeho<br />

tvar a používání je<br />

overload name_fce;<br />

name_fce je jméno přetěžované funkce. Příkaz předchází deklaracím přetěžované funkce.<br />

8.3 Přetěžování a nejednoznačnost<br />

Při používání přetěžování funkcí se může do programu zanést nejednoznačnost. Bývá to<br />

převodem typů, pomocí parametrů odkazů, pomocí standardních argumentů. Někdy ale<br />

nejednoznačnost je vnesena samotným přetížením funkce. Ukázkou je následující příklad.<br />

Příklad 51<br />

float fce_1(float x)<br />

{ return x/2.0; }<br />

double fce_1(double x)<br />

{ return x/3.0; }<br />

int main()<br />

{ float x=1.01;<br />

dougle y=1.01, a;<br />

a= fce_1(x); // jednoznačné<br />

a= fce_1(y); // jednoznačné<br />

a= fce_1(48);// nejednoznačné, převod 48 na double nebo float<br />

return 0;<br />

str. 52


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

};<br />

Podobně by se s různými typy dalo pokračovat.<br />

8.4 Úkol<br />

1. Sestavte program, který pomocí zjednodušeného zápisu umožní více typů<br />

zobrazení aktuálního data, hodiny.<br />

str. 53


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

9 Šablony funkcí a tříd<br />

Šablony jsou vzory, podle kterých překladač může sestavit skupiny podobných vlastností.<br />

Tyto skupiny se nazývají případy (instance) šablony. Deklarace šablony má tvar<br />

template deklarace;<br />

template je klíčové slovo, které uvádí deklaraci šablony, seznam_parametru je seznam<br />

formálních parametrů, deklarace je deklarace obyčejné funkce, metody, objektového typu,<br />

statické datové složky objektového typu.<br />

Šablony nemohou být lokální ve funkcích, šablony funkcí se mohou deklarovat na<br />

úrovni souboru, šablony objektových typů můžeme deklarovat na úrovni souboru, jako složky<br />

objektových typů nebo šablon objektových typů. Lokální třídy nemohou obsahovat deklarace<br />

šablon. Dále existuje ještě několik pravidel nebo zaběhlých použití šablon.<br />

9.1 Parametry šablon<br />

Rozlišují se hodnotové, typové a šablonové parametry. Typový parametr zastupuje<br />

datový typ, hodnotový parametr zastupuje konstantu. Hodnotové parametry se deklarují<br />

podobně jako formální parametr funkce. Typový parametr se deklaruje pomocí klíčového<br />

slova class. Pokud předepíšeme, že parametr je šablona, získáme poslední typ parametru.<br />

Příklad 52<br />

class test<br />

class test =int<br />

typename test<br />

typename test=float<br />

template< class test, ...>class test_1<br />

// první tvar<br />

// druhý tvar<br />

// třetí tvar<br />

// čtvrtý tvar<br />

// pátý tvar<br />

templateclass test_1=Jmeno_Sablony<br />

//šestý tvar<br />

První a třetí tvar představuje typový formální parametr bez implicitní hodnoty. Druhá a čtvrtá<br />

možnost prezentuje typový formální parametr s implicitní hodnotou. Pátý a šestý tvar<br />

zachycují šablonový formální parametr.<br />

9.2 Šablony funkcí<br />

Zápis šablony funkce je následující<br />

template typ jmeno (seznam_parametru_fce )<br />

{ telo fce<br />

};<br />

Uveďme si na příkladech.<br />

Příklad 53<br />

str. 54


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

templatetest ma(test a, test b)<br />

{ return a>ba:b;<br />

};<br />

Příklad 54<br />

#include <br />

using namespace std;<br />

template void prohod(X &a, X &b) //šablona funkce<br />

{ X pom; //X je vlastníkem prostoru<br />

pom = a;<br />

// vloží a do pom<br />

a = b;<br />

//prohodí b do a<br />

b = pom;<br />

//vloží do b hodnotu z pom<br />

}<br />

int main()<br />

{<br />

int i=100, j=200;<br />

float x=100.1, y=200.3;<br />

cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

using namespace std;<br />

template class mojetrida<br />

{ T1 i;<br />

T2 j;<br />

public:<br />

mojetrida(T1 a, T2 b) { i = a; j = b; }<br />

void vypis() { cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

10 Obsluha výjimek<br />

Jazyk <strong>C++</strong> má vestavěn mechanismus pro ošetření chyb nazvaný obsluha výjimek.<br />

Ošetření se děje pomocí klíčových slov try, catch, throw. Mechanismus pro zpracování<br />

výjimek dokáže oddělit běžný zdrojový kód od kódu pro zpracování chyby. Syntaxe je :<br />

try { pokusny_blok }<br />

catch(typ1[identifikator])<br />

{ telo_osetreni_vyjimky<br />

}<br />

catch(typ2[identifikator])<br />

{ telo_osetreni_vyjimky<br />

}<br />

catch(typn[identifikator])<br />

{ telo_osetreni_vyjimky<br />

}<br />

pokusny_blok je kód, v němž může nastat výjimka, v bloku catch je uveden případ pro<br />

zadanou výjimku. Pokud nastane výjimka a není zde uvedeno tělo catch, může dojít<br />

k nekorektnímu ukončení programu. Nenastane-li ani jedna výjimka, všechny bloky catch<br />

jsou přeskočeny.<br />

Nechceme-li přístup k samotné výjimce, v klíčovém slovu catch specifikujeme pouze<br />

typ. Pro upřesnění, které výjimky se smějí rozšířit z těla funkce, se používá funkce throw.<br />

Jednoduchý program ošetření výjimek je uveden jako Příklad 57.<br />

Příklad 57<br />

void test(int x)throw(int, char, double)<br />

{ if(x==0) throw x; //odmítne int<br />

if(x==1) throw ’abcd’; //odmítne char<br />

if(x==2) throw 122.333; //odmítne double<br />

}<br />

int main()<br />

{ int err=0;<br />

try{ test (0)}<br />

catch(int i) { err=1;}<br />

catch(char c) { err=2;}<br />

catch(double d) { err=3;}<br />

return err;<br />

}<br />

V příkladu je definovaná funkce test, která zachycuje výjimky s omezené množiny (celé<br />

číslo, znak, reálné číslo s dvounásobnou přesností). V hlavní funkci se deklaruje proměnná<br />

err a volá se blok try s funkcí test. Pak proběhne zachycení výjimek. Podle jejich pořadí<br />

je do proměnné err zapsána hodnota, která se předá na konci hlavní funkce.<br />

Jako doplnění pro ošetření výjimek slouží funkce unexpected(), terminate(),<br />

set_unexpected(), set_terminate(). Funkce unexpected(), terminate() volají<br />

str. 57


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

systém v případě ukončení programu. Funkce set_unexpected(), set_terminate()<br />

mohou změnit nastavení funkcí unexpected(), terminate().<br />

Příklad 58<br />

#include <br />

using namespace std;<br />

int main()<br />

{ cout


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

10.1 Úkol<br />

1. Pro vámi sestavený program nastavte kontrolu neočekávaných výjimek tak,<br />

abyste jej ošetřili proti nestandardnímu ukončení.<br />

str. 59


Seminář <strong>C++</strong><br />

VUT FEKT v Brně<br />

11 Závěr<br />

Společně jsme prošli základy programování v jazyce <strong>C++</strong> a bodově se dotkli některých<br />

hlavních témat. Měli bychom mít osvojeny základní návyky programátora jako je např.<br />

využívání různých druhů vysvětlujících textů. Kurz nabízel použití vývojového prostředí<br />

Borland <strong>C++</strong> Builder pro platformu MS Windows a z 90 % se zaměřil na programy<br />

klasického typu (událostmi řízené programování se probíralo v kurzu Počítače<br />

a programování II). Učinili jsme první kroky k schopnosti vyvíjet praktické aplikace pro<br />

řešení problémů z oblasti elektrotechniky, informatiky a komunikačních technologií. Nejlepší<br />

školou programování je vlastní práce s jasně definovaným cílem. Zde byly pokryty základy<br />

programování, které budete muset již sami rozvíjet, seznamovat se s dalšími možnostmi, které<br />

Borland <strong>C++</strong> Builder nebo jiné nadplatformní programy nabízí a sledovat vývoj, jímž<br />

programovací nástroje procházejí. Velmi rychle se měnící informační technologie způsobují,<br />

že programátoři musejí nové informace a trendy studovat celý život. Při tomto neustálém<br />

studiu vám přeji mnoho úspěchů a pevně věřím, že nabyté znalosti využijete dále, např. při<br />

řešení ročníkových projektů, bakalářských a diplomových prací.<br />

11.1 Literatura<br />

[1] ECKEL, B. Myslíme v jazyku <strong>C++</strong>. Praha: Grada Publishing, 2002. ISBN 8-0247-9009-2<br />

[2] VIRIUS, M. Programovací jazyky C/<strong>C++</strong>. Praha: Gcomp, 1992. ISBN 8-0901-0735-4.<br />

[3] PRATA, S. Mistrovství v <strong>C++</strong>. Praha: Computer Press, 2001. ISBN 8-0722-6339-0<br />

[4] KADLEC, V. Učíme se programovat v Borland <strong>C++</strong> Builder a jazyce <strong>C++</strong>. Praha:<br />

Computer Press, 2001. ISBN 8-0722-6550-4<br />

[5] HOLAN, T., NERUDA, R. <strong>C++</strong> Builder v příkladech. Praha: BEN, 2002. ISBN 8-0730-<br />

0042-3<br />

[6] HEROUT, P. Učebnice jazyka C. České Budějovice: Kopp, 1992. ISBN 8-0858-2821-9<br />

[7] HEROUT, P. Učebnice jazyka C, 2.díl. Č. Budějovice: Kopp, 1992. ISBN 80-85828-50-2<br />

[8] Virius,M.a kol. Jazyky C a <strong>C++</strong> podle normy ANSI/ISO. GRADA, 1999. ISBN 80-7169-<br />

631-5<br />

[9] Schildt,H. Nauč se sám <strong>C++</strong>. Softpress, 2001. ISBN 80-86497-13-5<br />

str. 60

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!