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