Upozornění pro čtenáře a uživatele této knihy

Všechna práva vyhrazena. Žádná část této tištěné či elektronické knihy nesmí být reprodukována ani šířena v papírové, elektronické či jiné podobě bez předchozího písemného souhlasu nakladatele. Neoprávněné užití této knihy bude trestně stíháno.

Miroslav Virius

Programování v jazyce C++

od základů k profesionálnímu použití

Vydala Grada Publishing, a.s.

U Průhonu 22, 170 00 Praha 7

tel.: +420 234 264 401, fax: +420 234 264 400

www.grada.cz

jako svou 6791. publikaci

Odpovědný redaktor Petr Somogyi

Sazba Petr Somogyi

formát ePub vytvořil Petr Somogyi

Počet stran 416

První vydání, Praha 2018

© Grada Publishing, a.s., 2018

Cover Design © Grada Publishing, a.s., 2018

V knize použité názvy programových produktů, firem apod. mohou být ochrannými známkami nebo registrovanými ochrannými známkami příslušných vlastníků.

Vytiskly Tiskárny Havlíčkův Brod a.s.

ISBN 978-80-271-0957-9 (ePub)

ISBN 978-80-271-0956-2 (pdf)

ISBN 978-80-271-0502-1 (print)

Předmluva

Kniha, kterou držíte v ruce, vás seznámí se základy programování v jazyce C++. Je určena jak čtenářům, kteří ještě vůbec neprogramovali, tak i těm, kteří již v nějakém jazyce programovali a chtějí se seznámit s jazykem C++. Předpokládám, že čtenář je sice začátečníkem v programování, ale umí s počítačem zacházet uživatelsky, tedy dokáže spustit program, zkopírovat nebo smazat soubor atd. V průběhu dvaceti kapitol této knihy se jej pokusím dovést na úroveň lehce pokročilého programátora.

Co v této knize najdete

Jediným způsobem, jak se naučit nějaký programovací jazyk, je psát v něm programy, a proto už ve druhé kapitole začneme programovat. Cílem druhé, třetí a čtvrté kapitoly je uvést na scénu vybrané konstrukce jazyka C++ a umožnit čtenářům zkoušet si vše, o čem si v následujících kapitolách povíme, na vlastních programech – jednoduchých a možná nešikovných, ale fungujících.

Než se ovšem pustíme do programování, musíme si ujasnit některé pojmy a sjednotit terminologii. Proto se v první kapitole seznámíme s pojmy, které budeme používat. Povíme si, co je třeba vědět o počítači, o programovacích jazycích, algoritmech, objektově orientovaném programování a některých dalších věcech, bez nichž se při programování neobejdeme.

Ve druhé kapitole napíšeme svůj první program, ukážeme si, jak ho přeložit (neboť jazyk, v němž ho píšeme, je jiný než jazyk, v němž „myslí“ počítač) a jak ho spustit. Seznámíme se s integrovaným vývojovým prostředím Code::Blocs a s překladačem g++, které budeme v této knize používat.

Ve třetí kapitole napíšeme několik verzí jednoduchých programů, které přečtou číslo, vypočtou z něj jistou hodnotu a výsledek vypíší. To nám umožní seznámit se alespoň povrchně s některými základními programovacími konstrukcemi, s rozdělením programu do několika souborů, s pojmem projektu apod. Se znalostmi z této kapitoly byste měli být schopni zkoušet si vše, co se v dalších kapitolách naučíte, na vlastních programech.

Ve čtvrté kapitole si ukážeme jednoduchý objektový program, seznámíme se velmi povrchně se šablonami a předvedeme si, jak ladit program – tedy jak zjistit, proč dělá něco jiného, než co jsme chtěli naprogramovat.

Od páté kapitoly začíná výklad „naostro“. Po seznámení se základními pojmy postupně poznáme vestavěné datové typy, příkazy jazyka C++, naučíme se používat tzv. pole a ukazatele. V deváté kapitole napíšeme první větší program – jednoduchou hru, v níž počítač klade otázky a podle uživatelových odpovědí hádá zvíře.

V následujících kapitolách se seznámíme s uživatelem definovanými neobjektovými typy, s výrazy a deklaracemi, s funkcemi, s preprocesorem jazyka C++, s objektovými typy a s tzv. výjimkami (nástroj pro ošetřování chyb za běhu). V předposlední kapitole probereme nástroje pro vstupní a výstupní operace (tedy pro čtení údajů z klávesnice, ze souboru apod.) a pro zápis údajů na obrazovku, do souboru apod.

V poslední kapitole postupně vyvineme několik verzí programu pro seřazení obsahu textového souboru. Jde o analogii filtru sort, který je standardní součástí běžných operačních systémů; naše verze se ovšem bude od standardního programu v mnoha ohledech lišit. To nám umožní seznámit se s řadou nástrojů ze standardní knihovny jazyka C++ a s některými užitečnými programátorskými technikami.

V poslední kapitole si krátce povíme o věcech, o nichž jsme v této knize nehovořili nebo jsme si řekli jen nejnutnější informace, ale které by měl pokročilý programátor v C++ znát.

Nástroje

Výklad v této knize je založen na mezinárodním standardu jazyka C++ [3] z roku 2017. Pro psaní, překlad, sestavení a ladění programů používáme vývojové prostředí Code::Blocs, které lze zdarma získat na stránkách [15] spolu s překladačem g++. Vedle toho zde najdeme poznámky pro čtenáře, kteří se rozhodnou pro Visual C++, jehož základní verzi lze také získat zdarma. Poznamenejme, že verze 4.9.2 překladače g++, která je implicitně dodávána s prostředím Code::Blocs, ve skutečnosti implementuje jazyk C++ na úrovni standardu z roku 2011. Není však problém instalovat si a používat nejnovější verzi tohoto překladače (v době dokončování této knihy to byla verze 6.4), která plně implementuje standard z roku 2014 a většinu novinek standardu z roku 2017. Místo překladače g++ si také můžete instalovat jakýkoli jiný překladač C++. Je však třeba poznamenat, že rozšíření, která přinesly pozdější verze standardu, v této knize nepoužívám, neboť výklad o nich přesahuje možnosti knihy určené začátečníkům.

Terminologie

V celé knize používám důsledně českou terminologii. Vím, že má mnoho odpůrců, jsem však přesvědčen, že použití vhodných českých názvů výrazně usnadní pochopení, oč jde. Anglické termíny samozřejmě uvádím alespoň při prvním výskytu také.

Příklady

Výklad v této knize doprovází velké množství příkladů. Jejich zdrojové texty si můžete stáhnout z webových stránek nakladatelství Grada Publishing (www.grada.cz, vyhledejte příslušnou sekci této knihy), nebo z mých osobních stránek, jejichž adresu najdete dále. Tyto příklady jsem odladil pod překladačem g++ verze 4.9.2 a pod Visual C++ 2015.

Poděkování

Na závěr bych chtěl poděkovat všem, kteří svými radami a připomínkami napomohli zdárnému dokončeni tohoto díla, především pak Ing. Rudolfu Pecinovskému, CSc., z VŠE v Praze a Ing. Vladimiru Jarému, Ph.D., z KSI FJFI ČVUT, kteří četli vybrané části této knihy a měli k nim řadu připomínek. I přes veškerou péči, kterou jsem této knize věnoval, se do ní ovšem mohly vloudit chyby; za ty nesu pochopitelně veškerou zodpovědnost já. Jestliže v této knize nějakou chybu najdete, pošlete mi prosím zprávu na níže uvedenou adresu. Bude-li to možné, uveřejním na svých webových stránkách opravu.

Ženeva, CERN, 21. srpna 2017

Miroslav Virius

miroslav.virius@fjfi.cvut.cz

http://people.fjfi.cvut.cz/virius

1Než začneme

Než si začneme povídat o programovacím jazyce C++, musíme se alespoň povrchně seznámit s některými pojmy, které budeme používat. Začneme od počítače jako takového, pak si něco povíme o programovacích jazycích, algoritmech a objektově orientovaném programování a skončíme u C++ a nástrojů, které budeme potřebovat. Některé z uvedených pojmů nepochybně znáte; přesto vás prosím, abyste si toto povídání alespoň zběžně přečetli, abychom se mohli shodnout na terminologii.

1.1Počítač

S osobními počítači se v současné době setkáváme denně – najdeme je nejen v každé kanceláři, ale i v téměř každé domácnosti. Dovolím si tedy předpokládat, že s počítačem umíte zacházet jako uživatelé – umíte ho zapnout, vytvořit na něm textový dokument apod. Ovšem programátor (a to i začínající) o něm musí přece jen vědět víc než běžný uživatel. I když bude povídání v této kapitole silně zjednodušené, pro naše účely bude stačit.

Obvykle se říká, že počítač obsahuje čtyři základní části:

■Procesor je součást, která opravdu „počítá“, lépe řečeno která zpracovává informace. Zároveň také řídí činnost všech ostatních částí počítače.

■Operační paměť slouží k ukládání dat (informací), která počítač zpracovává, a programů, tedy příkazů, které určují, co má dělat. Vše, co je v této paměti, se při vypnutí počítače ztratí, „zapomene“. Používá se pro ni označení RAM, což je zkratka anglických slov Random Access Memory, tedy paměť s náhodným přístupem.

■Vstupní a výstupní zařízení slouží k výměně informací s okolím. (Počítač by nám nebyl nic platný, kdyby nám nemohl předat výsledky své práce.) Typickými příklady vstupních zařízení jsou klávesnice, myš, skener atd. Typickým příkladem výstupních zařízení může být obrazovka monitoru nebo tiskárna. Pro vstupní a výstupní zařízení se používá zkratka V/V nebo I/O (z anglického input/output).

■Trvalá paměť slouží k trvalému ukládání dat a programů.[1] Data v ní se při vypnutí počítače neztrácejí, má zpravidla mnohonásobně větší kapacitu než operační paměť, ale práce s ní je mnohonásobně pomalejší než práce s operační pamětí. Jako trvalá paměť se používají převážně magnetické disky (pevný disk, disk SSD – jeho název pochází z anglických slov solid state drive a je to paměťové zařízení podobné jako flash disk neboli „fleška“, ovšem s větší kapacitou) a samozřejmě také disky CD nebo DVD.

1.1.1Operační paměť

Základem operační paměti jsou elektronické obvody, které mohou mít dva stavy – například vypnuto nebo zapnuto. Jeden z těchto stavů obvykle odpovídá číslici 0, druhý číslici 1. Údaje v paměti jsou proto vyjádřeny jen pomocí nul a jedniček, v tzv. dvojkové soustavě. Místo, na které můžeme uložit číslici 0 nebo 1, označujeme jako bit. Operační paměť je tedy dlouhá řada bitů.

Ovšem práce s jednotlivými bity je nepohodlná, a proto se bity sdružují do větších celků. V dnešních počítačích se téměř bez výjimky používají skupiny velikosti 8 bitů, které se nazývají bajty (anglicky byte, tedy slabika). Poznamenejme, že pro bity se používá značka b a pro bajty značka B.

Jednotlivé bajty, tvořící operační paměť, jsou očíslovány. Počáteční bajt má číslo 0, následující má číslo 1 atd. Toto pořadové číslo se nazývá adresa bajtu. (Ve skutečnosti může být záležitost s adresami trochu složitější, ale to nás v souvislosti s C++ vůbec nebude zajímat.)

1.1.2Soustava SI, bity a bajty

Vnitřní paměť běžného počítače má dnes velikost několik miliard bajtů, kapacita disků a podobných zařízení se vyjadřuje v bilionech bajtů. Podobně jako v běžném životě nevyjadřujeme například vzdálenosti měst v metrech, ale v kilometrech, i v informatice se používají k vyjádření kapacity paměti (nebo obecně množství informace) větší jednotky. Běžně se hovoří o kilobajtech (kB), megabajtech (MB), gigabajtech (GB) atd.

Vzhledem k tomu, že počítače jsou založeny na dvojkové soustavě, je však přirozenější používat jednotky založené na mocninách dvou, nikoli na mocninách deseti, jak je tomu v soustavě SI. Proto by se měly používat jednotky kibibajt (1 KiB = 2^10 B = 1024 B), mebibajt (1 MiB = 1024 KiB = 2^20 B = 1048576 B), gibibajt (1 GiB = 2^30 B = 1073741824 B) atd. Předpony těchto jednotek jsou složeny z první slabiky odpovídající předpony soustavy SI a slabiky bi ze slova binary.[2]

1.2Datové typy a proměnné

Snadno zjistíme, že nejmenší číslo, které může jeden bajt obsahovat, se skládá z osmi nul a představuje i v desítkové soustavě nulu. Největší takové číslo se bude skládat z osmi jedniček a v desítkové soustavě představuje 255. To je samozřejmě málo – s počítačem, který by znal jen čísla od 0 do 255, bychom si nedokázali ani přepočítat výplatu. Proto se pro ukládání dat obvykle používají různě velké skupiny za sebou následujících bajtů.

Ani to ovšem nestačí. Snadno se přesvědčíme, že kdybychom vzali například skupinu dvou za sebou následujících bajtů, mohli bychom do ní uložit celá čísla v rozmezí od 0 do 65 535. Ale co když budeme potřebovat záporná čísla? Co když budeme potřebovat reálná čísla? Co když budeme chtít vyjádřit znaky nebo logickou hodnotu (nějaké tvrzení platí nebo neplatí)?

Musíme tedy zajistit způsob, který nám umožní reprezentovat data různých „druhů“ v paměti počítače. Jinými slovy, musíme najít způsob, jakým určité skupině bitů přiřadíme hodnotu, kterou tato skupina představuje – jak ji v počítači zakódovat.

Můžeme se například dohodnout, že bajt s hodnotou 01000001 bude představovat znak ‘A’. Táž skupina bitů může za jiných okolností ovšem také představovat celé číslo, které má hodnotu 65. Stejný bajt ale může být i součástí většího celku s úplně jiným významem.

Předchozí příklady ukazují, že pracuje-li počítač s nějakým kouskem paměti, s nějakou skupinou za sebou následujících bajtů na určité adrese, musí vědět, jak je tato skupina velká a jak má její obsah interpretovat. Jinými slovy, musí znát datový typ hodnoty, která je tam uložena, musí vědět, zda jde o celé číslo, znak, logickou hodnotu atd.

Podle datového typu se také budou lišit operace, které lze s danou hodnotou provádět. Celá čísla lze například sčítat a odečítat, znaky lze spojovat do řetězců, tedy do souvislého textu.

Nyní se na celý problém podívejme trochu jinak. Už víme, že když budeme chtít pracovat s nějakou hodnotou, musíme si ji uložit do paměti. To ale znamená, že si tam pro ni musíme vyhradit místo a říci, jakého typu budou údaje, které bude obsahovat. Takové místo pro ukládání hodnoty budeme nazývat proměnná.

Abychom s proměnnou mohli zacházet, musíme ji pojmenovat, musíme jí přidělit identifikátor. Tomu se v programování říká deklarace proměnné.[3]

1.3Programy a programovací jazyky

Aby mohl počítač nějak zpracovávat data, která mu předložíme, musíme mu také říci, co má vlastně dělat – musíme mu dát program.

Procesor umí s daty řadu operací, ovšem velice jednoduchých. Lze mu například říci „vezmi celé číslo, které je na adrese 6548, a přičti k němu celé číslo z adresy 7895“. Protože do jeho paměti nelze uložit nic jiného než čísla, musí být tyto příkazy vyjádřeny – zakódovány – také čísly. Toto číselné vyjádření instrukcí (příkazů) pro procesor se nazývá strojový kód a je to jediná věc, které procesor rozumí. Jedním z problémů je, že různé druhy počítačů používají různé strojové kódy, takže programy ve strojovém kódu nejsou přenositelné mezi počítači s různými procesory.

Jiným – a možná horším – problémem je, že programování ve strojovém kódu je velice namáhavé a nepřehledné. Také to téměř nikdo nedělá; místo toho se používají tzv. vyšší programovací jazyky – PHP, Java, C, Basic, a také C++.

Zápis programu ve vyšším programovacím jazyce se zpravidla skládá z vybraných anglických slov a z výrazů zapsaných podobně jako v matematice. Programování ve vyšším jazyce je pochopitelně daleko jednodušší než programování ve strojovém kódu. Je tu ovšem jeden háček: takovýto program nelze přímo spustit, neboť počítač mu nerozumí. Program ve vyšším programovacím jazyce se proto musí buď přeložit do strojového kódu, nebo interpretovat. V obou případech k tomu potřebujeme další program (nebo skupinu programů), které to za nás udělají.

Zápis programu ve vyšším programovacím jazyce se zpravidla označuje jako zdrojový kód nebo zdrojový program, v „programátorštině“ zdroják. Textový soubor, který tento zápis obsahuje, označujeme jako zdrojový soubor. O jeho překlad do strojového kódu (kompilaci) se stará program zvaný překladač neboli kompilátor (anglicky nazývaný compiler). V mnoha případech s ním spolupracuje ještě sestavovací program neboli linker, který může spojit několik nezávisle přeložených částí programu do jednoho celku. Sestavovací program také připojí knihovny – části programu, které už někdo naprogramoval předem a které můžeme už jen používat.

Překladem a sestavením programu vznikne soubor obsahující strojový kód, který lze na cílovém počítači rovnou spustit. Mezi často používané překládané programovací jazyky patří například C nebo C++.

Můžeme však také použít speciální program, jenž bude číst zdrojový text a provádět příkazy, které v něm najde – interpretovat ho. Typickým interpretovaným jazykem je klasický Basic.[4]

Interpretované programy zpravidla běží výrazně pomaleji než překládané programy. Navíc musíme na cílový počítač spolu s naším programem dodat také interpretační program.

Doplňme, že překladač libovolného programovacího jazyka (i C++) zároveň kontroluje syntaktickou správnost programu – tedy zda program je napsán podle jistých formálních pravidel, které zaručují, že mu počítač porozumí. (Syntaktická správnost programu bohužel nezaručuje věcnou správnost programu, tedy nezaručuje, že program bude dělat to, co si přejeme. Zaručuje pouze, že ho překladač dokáže přeložit.)

1.3.1Jazyk C++

Už víme, že C++ patří mezi překládané programovací jazyky. Jeho zdrojový kód se může skládat z několika souborů. Překlad takového programu probíhá ve třech základních fázích:

1.Nejprve preprocesor upraví zdrojové texty – odstraní z nich komentáře (v následující kapitole se dozvíme, co to znamená) a provede některé další úpravy. Výsledkem jsou zdrojové soubory připravené k vlastnímu překladu.

2.Pak překladač přeloží samostatně jednotlivé zdrojové soubory. Překladem z nich vzniknou tzv. relativní soubory (anglicky nazývané object file). Relativní soubor se typicky jmenuje stejně jako zdrojový soubor, má však jinou příponu – pod Windows to je zpravidla .obj, v prostředí Linuxu to je .o.

3.Nakonec sestavovací program (linker) spojí relativní soubory v jeden celek, připojí k nim potřebné knihovny (už hotové součásti, které má překladač k dispozici) a vytvoří z nich spustitelný soubor; ten má pod Windows příponu .exe. V jiných operačních systémech nemusí mít žádnou zvláštní příponu.

Preprocesor, překladač a linker mohou být – a dnes zpravidla jsou – spojeny do jednoho programu, který provede postupně všechny potřebné kroky. Přepínači zadanými při spuštění tohoto programu lze ovšem zajistit, že proběhne například jen zpracování preprocesorem, jen zpracování preprocesorem a překlad nebo jen sestavení relativních souborů do spustitelného programu. Podrobněji se s tím seznámíme v příští kapitole.

1.3.2Asembler

Mezistupněm mezi strojovým kódem a vyššími programovacími jazyky je asembler (assembler, assembly language). Je to jazyk složený především z mnemotechnických zkratek jednotlivých instrukcí strojového kódu. Například instrukce:

MOV EAX, 0

znamená v jednom z asemblerů procesorů Intel používaných na PC „ulož 0 do registru EAX“. (Registry jsou součásti procesoru, v nichž se provádějí operace s daty.) Asembler také zavádí proměnné jako pojmenovaná místa v paměti, a proto se pro ně dříve používalo označení jazyk symbolických adres. Poznamenejme, že pro jeden procesor může existovat (a zpravidla existuje) více asemblerů.

Programování v asembleru je sice nesrovnatelně jednodušší než programování ve strojovém kódu, ale na druhé straně je nesrovnatelně obtížnější než programování ve vyšších programovacích jazycích.

Překladače C++ zpravidla umožňují vytvořit také překlad zdrojového kódu do asembleru.

1.4Operační systém

S počítačem se typicky dodává vždy alespoň jeden program, a to operační systém. To je program, který startuje automaticky hned po spuštění počítače a běží po celou dobu jeho běhu. „Oživuje“ počítač: přijímá pokyny uživatele (nerozhoduje, zda jsou vyjádřeny slovem zapsaným v příkazové řádce nebo kliknutím na myší na ikoně), stará se o jejich provedení a informuje uživatele o výsledcích.

Vedle toho ovšem má ještě řadu dalších úloh, z nichž pro nás nejdůležitější je, že poskytuje služby běžícím programům. Stará se o jejich spouštění, o přidělování paměti, poskytuje nástroje pro práci se soubory atd. Chceme-li například v programu otevřít soubor, program prostě předá náš požadavek operačnímu systému a ten se postará o vše potřebné.

Mezi nejznámější operační systémy na osobních počítačích patří různé verze Windows a Linuxu, na mobilních zařízeních je to například Android, iOS a další.

1.5Program a algoritmus

C++, podobně jako ostatní programovací jazyky, slouží k zápisu programu. Už víme, že program je nějaký soubor instrukcí (příkazů), které počítači říkají, co má dělat.

Program vždy představuje návod k provedení nějaké úlohy nebo k vyřešení nějakého problému. Přitom musíme mít na paměti, že počítač za nás problém nevyřeší, jen za nás udělá hrubou práci – prohledá obrovské množství záznamů v databázi, vypočítá něco podle složitých vzorců, vykreslí obrázek a podobně. My mu ovšem musíme říci, jak to má udělat. Jinými slovy, musíme mu poskytnout návod, jak dospět k požadovanému výsledku.

Tento návod musí mít určité vlastnosti. Některé z nich mohou vypadat jako samozřejmé, ale přesto je zde uvedeme:

■Návod musí vést k požadovanému výsledku.

■Musí se skládat z kroků, kterým počítač rozumí – tzv. elementárních kroků. (To pro nás znamená, že ho musíme umět zapsat v některém programovacím jazyce.)

■Těchto kroků nesmí být nekonečně mnoho. (Nejde o to, že bychom mohli napsat program, který je nekonečně velký; to se nám asi nepodaří. Není ale nic těžkého napsat krátký program, který nikdy neskončí, protože se v něm bude donekonečna opakovat určitá skupina instrukcí.)

■Po každém kroku musí počítač vědět, kterým krokem má pokračovat.

Návod, který tyto podmínky splňuje, se obvykle označuje jako algoritmus. Na program se můžeme dívat jako na zápis algoritmu v programovacím jazyce.

1.5.1Metoda shora dolů

Otázkou je, jak k algoritmu dospět. Je asi jasné, že nejprve musíme umět daný problém vůbec vyřešit sami,[5] a pak se můžeme snažit zapsat ho jako posloupnost elementárních kroků. Přitom se používá obvykle tzv. metoda shora dolů. Návod se rozkládá na menší a menší části, až dospějeme k elementárním krokům. Při tomto zjemňování se samozřejmě může stát, že budeme muset předchozí rozdělení upravit, některé kroky spojit, některé kroky přidat ap.

PŘÍKLAD 1.1: ŘAZENÍ ZADANÝCH HODNOT

Jako příklad metody shora dolů vezmeme tuto úlohu: Máme skupinu N číselných proměnných, které označíme A[0], A[1], ..., A[N-1]. Tato čísla chceme uspořádat tak, aby platilo:

A[0] ≤ A[1] ≤ ... ≤ A[N-1]   (1)

Nejprve zavedeme nové termíny, které nám usnadní vyjadřování.

Skupině proměnných stejného typu, se kterými můžeme zacházet jako s jedním celkem, říkáme v programování pole (v angličtině se používá termín array). Zde tedy máme pole A s prvky A[0], A[1], ..., A[N-1]. Čísla označující jednotlivé prvky pole se nazývají indexy.

Úloha „zpřeházet“ hodnoty uložené v prvcích tohoto pole, aby vyhovovaly podmínce (1), se nazývá třídění pole.[6] Naším úkolem tedy je setřídit pole A. Návod pro třídění pole A může vypadat takto:

1.Najdi v poli A prvek, který obsahuje nejmenší hodnotu, a vyměň ho s prvkem, který je na prvním místě (na místě s indexem 0).

2.Najdi v poli A prvek, který obsahuje druhou nejmenší hodnotu, a vyměň ho s prvkem, který je na druhém místě.

3.A takto postupuj dále, dokud není pole setříděné.

Ovšem program nemůže obsahovat nějaké „takto postupuj dále“ – musíme najít lepší formulaci. Přitom si ale stačí uvědomit, že v prvním kroku vyhledáme nejmenší prvek z celého pole a dáme ho na první místo (do prvku pole s indexem 0). Nejmenší hodnota je tedy už na svém místě a nemusíme se o ni starat. Proto nám ve druhém kroku stačí najít nejmenší prvek ze zbylého úseku pole A[1], ..., A[N-1] a ten dát na druhé místo, ve třetím kroku najít nejmenší hodnotu mezi prvky A[2], ... , A[N-1] atd. V posledním kroku budeme hledat nejmenší z prvků A[N-2], A[N-1]. Pak bude pole setříděné, tedy bude vyhovovat podmínce (1).

To znamená, že opakujeme podobnou akci (vyhledat nejmenší prvek v úseku pole a dát ho na první místo v tomto úseku) se stále menším úsekem pole. Zkoumaný úsek pole začíná postupně prvkem s indexem 0, 1, ..., N-1.

Z těchto úvah může vzejít lepší formulace. Bude používat pomocnou proměnnou i, která nám poslouží jako „počítadlo“.

1.Do proměnné i vlož hodnotu 0.

2.Mezi prvky A[i], ... , A[N-1] najdi nejmenší.

3.Vyměň ho s prvkem, který je na i-tém místě.

4.Zvětši hodnotu proměnné i o 1.

5.Je-li i < N-1, pokračuj krokem 2, jinak skonči.

Kroky 1, 4 a 5 můžeme považovat za elementární, kroky 2 a 3 je třeba zpřesnit.7 Podívejme se nejprve na krok 2. Budeme v něm potřebovat dvě pomocné proměnné. V jedné, kterou pojmenujeme třeba min, si budeme pamatovat index nejmenšího zatím nalezeného prvku, a druhá – k – nám poslouží jako „počítadlo“ při procházení zkoumaného úseku pole.

2. Mezi prvky A[i], ... , A[N-1] najdi nejmenší.

2a. Do obou pomocných proměnných, k a min, ulož i. (To je index počátečního prvku zkoumaného úseku. Zatím jsme prozkoumali jen jeden prvek, a tak ho pokládáme za nejmenší.)

2b. Zvětši k o jedničku. (Přejdi na další prvek v poli.)

2c. Je-li k = N, jdi na krok 3.

2d. Je-li A[k] ≤ A[min], ulož do min hodnotu k.

2e. Přejdi na krok 2b.

Po skončení bude proměnná min obsahovat index nejmenšího prvku v prohledávaném úseku.

Podobně můžeme ještě upřesnit bod 3. V něm budeme potřebovat pomocnou proměnnou x:

3. Vyměň prvek A[min] s prvkem A[i].

3a. Do pomocné proměnné x ulož hodnotu A[min].

3b. Do A[min] přesuň hodnotu A[i].

3c. Do A[i] přesuň hodnotu x.

Tyto kroky již můžeme pokládat za elementární.

1.5.2Metoda zdola nahoru

Občas se také hovoří o tzv. metodě zdola nahoru.[7] Tím se myslí, že budeme svůj počítač postupně učit nové elementární kroky, které poskládáme z kroků, jež počítač už umí. Jestliže například zjistíme, že ve svém programu často třídíme pole, naprogramujeme si tento algoritmus jednou provždy a později ho budeme už jen používat a pokládat za elementární krok.

Naprogramované – a pojmenované – dílčí algoritmy označujeme v jazyce C++ jako funkce nebo jako podprogramy.

Poznamenejme, že součástí každého programovacího jazyka jsou knihovny, jež obsahují řadu naprogramovaných běžných algoritmů a dalších součástí programů, které můžeme ve svých programech používat.

1.6Objekty a třídy

Od devadesátých let minulého století je v programování převládajícím přístupem objektově orientované programování (OOP). Jazyk C++ sice není čistě objektový, což znamená, že nevyžaduje objektový přístup, ale umožňuje ho a řada součástí jeho knihoven je na objektovém přístupu založena, a proto si o něm musíme povědět. V tomto oddílu si vysvětlíme základní principy. Až budeme znát základy C++, vrátíme se k nim a povíme si více.

1.6.1Zapouzdření

Zatím jsme uvažovali o programování a programech převážně z hlediska počítače, hardwaru. Od zobrazování dat v paměti jsme došli k datovým typům, od strojového kódu k programovacím jazykům. Pokusme se nyní na programování podívat z hlediska programátora, který stojí před úkolem něco vyřešit – ať už jde o program pro vedení účetnictví malé či velké firmy, počítačovou hru nebo systém řídící vstřikování paliva v automobilovém motoru. Program musí v každém případě odrážet vybrané stránky řešené úlohy, musí být jejím počítačovým modelem.

Je asi jasné, že programátorovi se bude lépe pracovat, bude-li moci uvažovat v termínech řešeného problému, než když bude muset uvažovat v termínech datových typů, které jsou jednou provždy dány jako součást programovacího jazyka. Jinými slovy, bylo by vhodné, aby si programátor mohl definovat své vlastní datové typy, které by mohl použít k programovému popisu řešené úlohy. V OOP se jim říká objektové typy neboli třídy, neboť popisují třídy objektů, které se vyskytují v řešeném problému.

Jako příklad si představme, že programujeme grafický editor. Jeho uživatel si v něm bude chtít kreslit obrázky složené ze základních geometrických tvarů – bodů, úseček, kružnic apod.

Programátor bude muset ve svém programu tyto grafické objekty nějak reprezentovat. Bude si muset vytvořit programový model bodu, úsečky atd. a bude muset naprogramovat také operace, které lze s grafickými objekty dělat.

Bod jako objekt

Co to znamená? Abychom si to ujasnili, zamysleme se například nad bodem. Z geometrie si nepochybně pamatujete, že bod v rovině (v našem případě na obrazovce monitoru) je určen svými souřadnicemi, tedy dvojicí reálných čísel. Vedle toho ovšem potřebujeme určit také jeho barvu; tu můžeme v počítači vyjádřit jedním celým číslem. Z toho plyne, že k reprezentaci bodu stačí skupina tří čísel. A s touto skupinou budeme chtít často zacházet jako s celkem.

Abychom mohli s bodem snadno pracovat, musíme popsat (naprogramovat) také operace, které s ním chceme dělat. Musíme ho umět vytvořit, zrušit, zobrazit, přemístit, zjistit jeho barvu, změnit jeho barvu, zjistit jeho polohu, změnit jeho polohu atd.

Třída, datová složka

V programu budeme určitě potřebovat větší množství bodů. Abychom nemuseli popisovat každý zvlášť, definujeme bod jako nový datový typ – jako třídu. Jednotlivé body, které nakreslí uživatel našeho grafického editoru, budou v programu představovány proměnnými (budeme také říkat objekty nebo instancemi) třídy bod. Každá instance třídy bod bude obsahovat datové složky,[8] které popisují jeho polohu a barvu.

Metoda

K zacházení s jednotlivými body budeme používat operace, které jsme k tomu účelu naprogramovali. Také tyto operace budou součástí definice třídy; v OOP se nazývají metody.

Při definici nového typu jsme udělali (zatím jen naznačili) dvě věci. Určili jsme:

■datovou reprezentaci nového typu,

■operace s ním (metody).

Ukrývání implementace

Jedno z pravidel objektového programování říká, že s datovými složkami bychom měli manipulovat pouze prostřednictvím metod. Tím před zbytkem programu skrýváme, jaká je skutečná datová reprezentace tohoto typu – ukrýváme jeho implementaci. Později si vysvětlíme, proč je to tak důležité.

Zapouzdření

Ukrývání implementace se v objektovém programování označuje jako zapouzdření (anglicky encapsulation). Někdy se pod tento pojem zahrnuje i společná definice datové reprezentace nového typu a operací s ním.

Objektový program

Objektový program se skládá pouze z objektů, tedy z instancí objektových typů, a tyto objekty si navzájem posílají zprávy. Mohou posílat také zprávy třídám jako celku. Zní to asi velice nesrozumitelně, ale v podání jazyka C++ to prostě znamená, že volají (spouštějí) své metody.

Vezměme opět grafický editor a podívejme se na něj jako na celek. Celá aplikace bude nejspíš představována instancí třídy editor, jednotlivé součásti obrázku budou představovány instancemi tříd bod, úsečka atd. Když uživatel stiskne tlačítko, kterým určí, že chce někde vytvořit nový bod, tedy instanci třídy bod, dozví se to editor. Ten požádá o vytvoření instance třídy bod (pošle třídě bod zprávu, která bude představovat žádost o vytvoření instance určitých vlastností). Bude-li třeba vybraný bod přemístit, pošle editor této instanci zprávu „přemísti se“, tedy zavolá odpovídající metodu.

Poznamenejme, že v objektovém programu představuje i třída samotná zvláštní objekt, kterému lze poslat zprávu – například žádost o vytvoření instance.

Modelovací jazyk UML

Při návrhu objektového programu se dnes často využívá tzv. jednotný modelovací jazyk (Unified Modeling Language, UML). Je to soubor pravidel pro vytváření diagramů, které popisují různé aspekty řešené úlohy. Mezi jiným popisuje také třídy a jejich instance, které se v úloze vyskytují, a jejich vzájemné vztahy.

Třídy a jejich vztahy popisuje tzv. diagram tříd (class diagram). Pro znázornění jednotlivých tříd se používá ikona ve tvaru obdélníka. V horní části je jméno třídy, pod ní – oddělený vodorovnou čarou – je seznam datových složek a pod ním, opět pod vodorovnou čarou, seznam metod. (Pokud seznamy datových složek nebo metod nepotřebujeme, můžeme je samozřejmě vynechat.) Možné znázornění třídy bod ukazuje obrázek 1.1.

Poznamenejme, že zejména ve složitějších diagramech se ve znázornění tříd vynechávají jak datové složky, tak metody a uvádějí se pouze jména tříd.

Obrázek 1.1 Znázornění třídy bod v jazyce UML

Skládání objektů

Pojďme dál. Vedle bodů budeme v programu potřebovat také kružnice. Jak víme, je každá kružnice určena svým středem a poloměrem. Vedle toho ovšem musíme ještě určit tloušťku čáry a její barvu. Mohli bychom tedy tvrdit, že k popisu kružnice nám stačí pětice čísel; ovšem podíváme-li se na to pozorněji, uvědomíme si, že střed kružnice je bod a k jeho popisu můžeme využít už hotový typ bod.

To znamená, že nový typ – třída – kružnice[9] bude popsán jednou instancí třídy bod a třemi čísly (poloměrem, barvou a tloušťkou čáry).

Podobně třída úsečka bude popsána dvěma body, barvou a tloušťkou čáry. Při definici nového typu nám nic nebrání použít jako datovou složku typ, který už existuje. Tomu říkáme skládání objektů.

Obrázek 1.2 Znázornění vztahu mezi třídami bod, úsečka a kružnice. Čísla, připojená ke spojnicím, vyjadřují, že kružnice obsahuje jeden bod, zatímco úsečka obsahuje dva body

Skládání objektů se v UML vyznačuje čarou zakončenou vyplněným kosočtvercem. Tato „šipka“ směřuje od třídy představující komponentu ke třídě, která ji používá (u té je onen kosočtverec; na druhé straně může být „obyčejná“ šipka). Vztah mezi třídami bod, úsečka a kružnice ukazuje obrázek 1.2.

1.6.2Dědění

Samotné zapouzdření je sice dobré, zlepšuje přehlednost programu, ale je to málo. Při psaní grafického editoru nejspíš brzy zjistíme, že velice často píšeme podobné úseky programu. V našem editoru budeme například chtít jako jednu z možností nabídnout otáčející se úsečku, třídu úsečka_rotující. Ta bude mít stejné vlastnosti jako obyčejná úsečka (bude popsána stejnými datovými složkami), navíc ale bude obsahovat údaj o rychlosti otáčení a metody, které nám umožní tuto rychlost zjišťovat a měnit.

Bylo by jistě nesmyslné při programování otáčivé úsečky opisovat znovu vše, co jsme naprogramovali pro obyčejnou úsečku. OOP proto nabízí mechanizmus nazvaný nepříliš šťastně dědění (inheritance), který umožňuje od existující třídy odvodit třídu novou.[10]

Odvozená třída bude obsahovat všechny datové složky a všechny metody předka; k nim můžeme přidat nové datové složky a nové metody. Můžeme také překrýt (změnit, předefinovat, override) některou z metod předka. Při dědění nemůžeme žádnou datovou složku ani žádnou metodu odstranit.

Vraťme se k našemu příkladu s otáčející se úsečkou. Třída úsečka_rotující, kterou odvodíme jako potomka třídy úsečka, bude obsahovat:

■Stejné datové složky jako rodičovská třída. My k nim přidáme novou datovou složku vyjadřující rychlost otáčení.

■Stejné metody jako rodičovská třída. My k nim přidáme metody pro zjištění a nastavení rychlosti otáčení a překryjeme metodu pro kreslení, neboť otáčející se úsečka se bude kreslit jinak než obyčejná úsečka.

Ovšem dědění se při práci na grafickém editoru uplatní ještě jinak. Při programování tříd vyjadřujících různé grafické objekty brzy zjistíme, že mnohé části programu jsou stejné nebo hodně podobné:

■Všechny třídy vyjadřující grafické objekty obsahují datovou složku popisující barvu a metody pro její zjištění a nastavení.

■Všechny tyto třídy obsahují metody pro nakreslení a smazání objektu.

■… a další.

Programovat jednu věc několikrát není nikdy dobré; jednak je to zbytečná práce navíc, jednak rozhodneme-li se něco změnit, musíme to měnit na několika místech a snadno se stane, že na některé místo zapomeneme.[11]

Proto bude rozumné vzít společné vlastnosti všech tříd grafických objektů z našeho programu a přenést je do společného předka. Tuto třídu výstižně nazveme grafický_objekt a ostatní třídy bod, úsečka a další pak odvodíme jako její potomky.

Obrázek 1.3 Dědická hierarchie tříd z příkladu o grafickém editoru

Jestliže bude třída grafický_objekt obsahovat například metodu nakresli, která objekt nakreslí, bude tuto metodu obsahovat i každá z odvozených tříd. Je ovšem pravděpodobné, že ji budeme muset v každém z potomků překrýt; přece jen úsečka se kreslí jinak než kružnice.

V UML znázorňujeme dědění pomocí nevyplněné trojúhelníkové šipky, která vede od potomka k předkovi. Třída, která je sama potomkem, může sloužit jako předek jiné třídy. Tak mohou vzniknout dědické hierarchie, posloupnosti tříd, navzájem odvozených děděním. Obrázek 1.3 ukazuje dědickou hierarchii tříd, o kterých jsme hovořili v příkladu o grafickém editoru.

1.6.3Polymorfizmus

Zamysleme se nyní nad během našeho grafického editoru. Uživatel si bude kreslit: to znamená, že bude vytvářet úsečky, rotující úsečky, kružnice a další instance jednotlivých tříd představujících grafické objekty. Se všemi se bude v programu zacházet velmi podobně. Bude třeba je vytvořit, určit jejich polohu, barvu atd., bude potřeba je nakreslit, možná smazat atd. Z našich předchozích úvah vyplynulo, že budou obsahovat řadu stejných metod. Bylo by tedy velice pohodlné, kdybychom s nimi mohli také v programu jednotným způsobem zacházet – kdybychom se nemuseli starat o konkrétní typ příslušné instance, kdyby stačilo vědět, že jde o instanci třídy, která je odvozena od společného předka, třídy grafický_objekt.

To opravdu v objektově orientovaném programování jde. Platí totiž velice důležité pravidlo: Potomek může vždy zastoupit předka. To znamená, že na místě, kde v programu očekáváme instanci předka, můžeme vždy použít instanci potomka.

V našem editoru tedy použijeme pro reprezentaci nakresleného obrázku například pole instancí třídy grafický_objekt a budeme do něj ukládat úsečky, kružnice, body – podle toho, co uživatel právě vytvoří.[12]

Když budeme chtít celý obrázek nakreslit, vezmeme prostě jednu instanci po druhé a pošleme jí zprávu, že se má nakreslit, tedy zavoláme její metodu nakresli. O skutečný typ instance se nebudeme starat: ať je jakéhokoli typu, metodu nakresli určitě obsahuje, neboť ji obsahuje společný předek. (V každém z odvozených typů je samozřejmě definována jinak.)

Této vlastnosti se říká polymorfizmus neboli mnohotvarost. Jeden objekt může mít mnoho tvarů. Například jedna instance třídy grafický_objekt může obsahovat podle okolností bod, kružnici…

Virtuální metoda

Metody, které se v různých třídách jedné hierarchie představují různou odezvu na tutéž zprávu, označujeme v C++ jako virtuální. Příkladem virtuální metody je metoda nakresli grafických objektů: všechny grafické objekty chceme kreslit, takže všechny ji budou mít. Zdědí ji od společného předka, třídy grafický_objekt, ale v každém z potomků bude dělat něco jiného – v jednom bude kreslit úsečku, v jiném kružnici atd. To znamená, že tuto metodu musíme v každém z potomků překrýt (override, setkáte se také s doslovným překladem „přebít“), naprogramovat, aby opravdu kreslila odpovídající objekt.

Abstraktní třída

Při úvahách o třídě grafický_objekt, jež představuje obecný grafický objekt, narazíme na malý problém: Jak se vlastně obecný grafický objekt kreslí?

Nijak – kreslit obecný grafický objekt přece nemá smysl, stejně jako nemá smysl třeba chtít kupovat obecnou potravinu nebo se ptát na výšku obecného stromu. Třída grafický_objekt je tzv. abstraktní třída, tedy taková, která představuje pojem natolik abstraktní, že určitá operace, typická pro všechny její podtřídy, pro něj nemá smysl. V našem případě nemá smysl uvažovat o kreslení obecného grafického objektu. Přesto je jasné, že třída grafický_objekt bude muset mít metodu nakresli, abychom ji mohli použít pro instance odvozené třídy – abychom mohli říci „nakresli tento grafický objekt“. Ve skutečnosti se budeme kreslit instance některého z odvozených typů, ale v době psaní programu nevíme jakého.

Metodu, která nemá v dané třídě konkrétní smysl, ale kterou musíme definovat, abychom ji mohli volat v odvozených třídách, označujeme také jako abstraktní; v C++ se pro ni také používá označení čistě virtuální (pure virtual).

Dědění versus skládání

Při vytváření tříd představujících grafické objekty bychom se mohli nechat svést následující úvahou: kružnice je popsána středem a poloměrem. Střed je bod. Odvodíme tedy třídu kružnice jako potomka třídy bod, do které přidáme datovou složku představující poloměr (a třída grafický_objekt pak bude zbytečná).

To by mohlo na první pohled fungovat. Jenže ono by to také znamenalo, že můžeme kružnici použít všude, kde program očekává bod – a to může vést k problémům, neboť kružnice není bod.

Odvozená třída totiž vždy znamená zvláštní případ bázové třídy. Úsečka je zvláštní případ grafického objektu; rotující úsečka je zvláštní případ úsečky. Proto má smysl odvodit třídu úsečka jako potomka třídy grafický_objekt a třídu úsečka_rotující jako potomka třídy úsečka. Na druhé straně kružnice není bod, takže odvodit třídu kružnice jako potomka třídy bod nemá smysl.

Ovšem kružnice má bod (střed). Proto má smysl použít skládání.

Předchozí úvahy ukazují něco, čemu se občas říká test je – má (anglicky is a – has a). Jestliže můžeme říci, že třída B je zvláštní případ třídy A, má smysl odvodit třídu B jako potomka třídy A. Jinak je vhodnější použít skládání.

1.6.4Objektové a neobjektové programování

V jazyce C++ můžeme programovat jak objektově, tak i neobjektově. Můžeme pochopitelně oba přístupy míchat, můžeme v neobjektovém programu používat objekty apod. Z předchozího výkladu plyne, že při neobjektovém přístupu se na program díváme jako na zápis algoritmu, zatímco při objektovém přístupu se na program díváme jako na skupinu objektů, které si navzájem posílají zprávy a na tyto zprávy reagují (spouštějí své metody). Ovšem cíl je v obou případech stejný, zpracovat zadaná data a poskytnout uživateli programu potřebný výsledek. To znamená, že i v objektovém programu budeme muset znát postup řešení zadané úlohy, implementujeme ho ovšem pomocí metod objektů, jež zapouzdří zpracovávaná data. Na druhé straně i v neobjektovém programu si musíme být vědomi zpracovávaných dat, jejich struktury a vzájemných vztahů – i když to nebudeme vyjadřovat pomocí objektových typů.

V této knize se seznámíme se základy obou uvedených přístupů.

1.6.5Poznámka k terminologii

V teorii objektově orientovaného programování znamená termín objekt totéž co instance. V souvislosti s programovacími jazyky C a C++ se však termín objekt používá v širším smyslu – jako označení manipulovatelné oblasti paměti. (Takto používají termín objekt i mezinárodní standardy [2] a [3].) Proto budeme v následujících kapitolách používat pouze termín instance.

1.7Céčko se dvěma plusy

Brzy se dozvíme, že zápis ++ v jazycích C a C++ znamená „vezmi následující hodnotu“; C++ je tedy následovník jazyka C. Jazyk C je skutečně předchůdcem jazyka C++, i když je dodnes také široce používán.

Jazyk C je neobjektový. Navrhl ho – a poprvé implementoval – Denis Ritchie v roce 1972 při práci na jedné z verzí operačního systému Unix. V roce 1978 o něm spolu s B. W. Kernighanem napsal knihu The C Programming Language, jež se stala na dlouhou dobu neoficiálním standardem tohoto jazyka. Od té doby bylo vydáno několik verzí mezinárodního standardu tohoto jazyka, poslední [2] v roce 2011.

Jazyk C++ navrhl a poprvé implementoval Bjarne Stroustrup v Bellových laboratořích v první polovině osmdesátých let minulého století. Původně představovalo C++ pouhé objektové rozšíření jazyka C a první programy v tomto jazyce se překládaly do jazyka C. Od té doby prošlo C++ prudkým vývojem; nyní obsahuje řadu nástrojů, které nejsou součástí jazyka C a které mohou významně usnadnit programování.

1.7.1Vývoj C++

Nejstarší verze jazyka C++ (z osmdesátých a devadesátých let minulého století) byly označovány Cfront; poslední verze, Cfront 3, byla vydána v roce 1991, v době, kdy už byl připravován mezinárodní standard. Pro nás jsou tyto verze jazyka nezajímavé, neboť s překladači, které je implementovaly, se už nesetkáme.

První mezinárodní standard jazyka C++ (ISO 14882) byl vydán v roce 1998. Druhá verze, vydaná v roce 2003, odstraňovala některá nedopatření z první verze. Tato verze bývá neformálně označována C++03.

Třetí verze, vydaná v roce 2011 a označovaná C++11, přinesla některá rozšíření jazyka – přibyla například možnost deklarovat šablony s proměnným počtem parametrů –, hlavně však doplnila řadu nástrojů do standardní knihovny, které programátoři postrádali. Jde mimo jiné o nástroje pro práci s regulárními výrazy, podporu vícevláknového programování a mnohé další.

V současné době platí mezinárodní standard [3] přijatý v roce 2014 a publikovaný na počátku roku 2015; je označovaný C++14. Tato verze přinesla drobná rozšíření jazyka (například generické lambda-výrazy) a knihoven (například další nástroje pro podporu vícevláknového programování).

V srpnu 2017, když jsem tuto knihu dokončoval, byla schválena nová verze standardu, označovaná C++17, nebyla však ještě publikována. Měla by přinést drobné úpravy jazyka (odstranit některá zbytečná omezení, usnadnit zápis některých konstrukcí apod.) a další rozšíření standardní knihovny.

Náš výklad bude vycházet z C++11. Nástroje, které přinesly novější verze, jsou určeny pokročilým programátorům a v knize určené začátečníkům se k nim nedostaneme.

Někteří dodavatelé překladačů se odvolávají na americký standard ANSI jazyka. Ten je samozřejmě shodný s mezinárodním standardem – přesněji je to převzatý standard ISO.

1.7.2Dvě úrovně znalostí C++

Při seznamování s jazykem C++ je třeba mít na paměti, že jsou dvě možné (výrazně rozdílné) úrovně znalostí:

■Základní úroveň, k níž se vás v této knize pokusím dovést, umožní programovat běžné úlohy a přitom využívat standardní a jiné programové knihovny, které jsou v jazyce C++ k dispozici.

■Úroveň programátora pokročilých knihoven vyžaduje hluboké porozumění rafinovaným nástrojům, které tento jazyk nabízí.

1.7.3Vývojové nástroje

Máme-li zdrojový kód programu, musíme ho přeložit a sestavit. K tomu samozřejmě stačí samostatný překladač; jestliže se však program skládá z více zdrojových souborů (a to je – kromě školních příkladů – téměř vždy), používají se ještě další nástroje, které usnadňují vývojářům práci. Zastavme se krátce alespoň u některých.

■Utilita Make (v různých prostředích se může jmenovat i jinak) je jednoduchý nástroj pro řízení překladu. Používá textový soubor označovaný makefile, v němž jsou příkazy, které určují podrobnosti překladu jednotlivých souborů, podrobnosti jejich sestavení do spustitelného souboru a další věci.

■Ladicí program (debugger) usnadňuje diagnostiku chyb v programu, které se projeví až za běhu (když program dělá něco jiného, než chceme).

■Profiler usnadňuje optimalizaci – umožňuje zjistit, „kde se ten program vlastně fláká“, tedy které části programu zaberou nejvíce času. Profilováním se v této knize zabývat nebudeme.

■Integrované vývojové prostředí, často označované zkratkou IDE (z anglického Integrated Development Environment) je program, který v sobě sdružuje textový editor pro vytvoření zdrojového kódu („napsání programu“), nástroj pro správu projektu,[13] umožňuje spustit program, obsahuje ladicí nástroje atd.

■Verzovací systémy umožňují archivovat předchozí verze programu, vracet se k nim, usnadňují spolupráci více programátorů na jednom projektu atd. Správou verzí ve verzovacích systémech se v této knize nebudeme zabývat.

1.7.4Kde získat potřebné nástroje

Chceme-li se naučit nějaký programovací jazyk, nemáme jinou možnost, než v něm začít psát programy, překládat je a spouštět. K tomu je ovšem potřeba mít překladač spolu se standardní knihovnou a pokud možno také vhodné vývojové prostředí.

Nástroje pro vývoj programů v C++ lze získat zdarma (nebo si je lze koupit, ale na to je čas, až se budete vývojem programů zabývat profesionálně). Podívejme se na některé z možností:

■Překladač g++ je součástí systému překladačů GCC vyvinutých pod patronací nadace Free Software Foundation a patří k nejznámějším a nejpoužívanějším volně dostupným nástrojům. Je k dispozici zdarma a jeho verzi pro Windows si lze stáhnout z webového portálu [9]; verze pro Linux je k dispozici například na portálu [11]. Implementace jazyka C++ v tomto překladači odpovídá platnému mezinárodnímu standardu z roku 2011. Podrobnější informace lze získat na portálu [10].

■Překladač Watcom C++ patřil v devadesátých letech minulého století k nejpoužívanějším komerčním překladačům, dnes je k dispozici zdarma. Lze ho získat na portálu [12].

■Integrované vývojové prostředí NetBeans bylo původně určeno pro programovací jazyk Java, lze ho ale používat i pro vývoj programů v jazycích C a C++. Je ovšem třeba instalovat si odpovídající doplněk. Lze ho získat zdarma na portálu [13].

■Integrované vývojové prostředí Code::Blocks představuje multiplatformní nástroj (je k dispozici pro operační systémy Windows XP a novější, 32bitovou a 64bitovou verzi Linuxu a Mac OS X) a lze ho získat na adrese [15]. Instalace pod Windows spolu s překladačem požaduje cca 234 MB prostoru na pevném disku. Toto prostředí se vzhledem ke své jednoduchosti hodí pro výuku začátečníků.[14]

Vedle toho existují i zdarma dostupné verze komerčních nástrojů. Ty zpravidla obsahují plnohodnotný překladač spolu se značně omezeným – i když pro naše účely plně dostačujícím – integrovaným vývojovým prostředím.

■Nástroj Microsoft Visual Studio Community 2017 obsahuje překladač, který je podle dostupných informaci na úrovni očekávaného standardu jazyka z roku 2017, a integrované vývojové prostředí pro Windows 7 a novější. Lze ho použít k výuce a k nekomerčním účelům a je dostupný na portálu [14]. Instalace vyžaduje zhruba 5 GB diskového prostoru.

1.7.5Co budeme používat

V této knize budu předpokládat, že máte k dispozici vývojové prostředí Code::Blocks s překladačem g++. Můžete se samozřejmě rozhodnout pro jiný překladač a jiné vývojové prostředí – výklad o programovacím jazyce to nijak neovlivní. Budou se lišit pouze příkazy pro překlad, s nimiž se setkáte v první části druhé kapitoly, a postupy některých operací ve vývojovém prostředí, o nichž se krátce zmíním ve třetí kapitole. Na možné odlišnosti se sice upozorním v poznámkách na konci odpovídajících oddílů, podrobnosti si však budete muset zjistit v dokumentaci ke svým nástrojům.

Pro integrované vývojové prostředí Code::Blocks budeme také používat zkratku CB.

1Setkáme se také s označením vnější paměť, neboť v dobách počítačové prehistorie byly magnetické disky opravdu uloženy mimo vlastní počítač. I dnes lze ovšem připojit k počítači vnější (externí) paměťové médium.

2Tyto jednotky byly zavedeny Mezinárodní elektrotechnickou komisí r. 1998, přijaty hlavními standardizačními organizacemi (jsou například součástí standardu [5]) a tvoří součást mezinárodního systému měrných jednotek.

3Později uvidíme, že identifikátor – tedy jméno – mohou mít i jiné části programu, nejen proměnné.

4Nehovoříme o Visual Basicu. Poznamenejme, že ve skutečnosti může být kterýkoli jazyk překládán nebo interpretován (existuje například interpret jazyka C++), takže by bylo přesnější hovořit o jazycích zpravidla překládaných a zpravidla interpretovaných.

5Algoritmům a metodám jejich návrhu je věnována řada knih; většina z nich ale předpokládá znalost určitého konkrétního programovacího jazyka. Asi nejznámější jsou knihy D. Knutha [1], které znalost konkrétního programovacího jazyka nepředpokládají, vyžadují ovšem matematické znalosti.

6Toto označení je nesmyslné – jde samozřejmě o řazení (uspořádání podle velikosti), nikoli o třídění (rozřazování do tříd). Mezi programátory se však pro tuto úlohu ujalo z nějakých záhadných důvodů označení třídění, a to nejen v češtině, ale i v mnoha jiných jazycích (v angličtině se také používá převážně označení sorting, nikoli ordering). Popsaná metoda se nazývá třídění výběrem (anglicky selection sort) a je vhodná pro menší pole.

7To prozatím berte jako fakt; z vašich dosavadních znalostí to nevyplývá.

8Setkáte se také s označením atribut. My se mu však budeme vyhýbat, neboť v současném C++ se tento termín používá v jiném smyslu.

9V programech se k pojmenování objektů, metod atd. dříve písmena s háčky a čárkami nepoužívala – většina starších programovacích jazyků to nedovolovala. Dnešní C++ to ovšem umožňuje (i když to nedovoluje překladač, s nímž budeme v této knize pracovat), a proto je budeme – alespoň v této kapitole – ve jménech užívat. Výrazně nám to usnadní pochopení diagramů, které nejsou závislé na žádném programovacím jazyce.

10Pro třídu, od které odvozujeme, se obvykle používá označení předek, rodičovská nebo bázová třída (base class). Pro třídu, kterou od ní odvodíme pomocí dědění, se používá označení potomek, odvozená nebo dceřiná třída (derived class). Místo dědění se také říká dědičnost.

11Pro zásadu neopakování se v programátorštině občas používá označení suchý princip. Jde o „překlad“ anglického označení DRY, které je zkratkou slov Don’t Repeat Yourself.

12Uvidíte, že v C++ to nebude tak jednoduché, ale o tom si povíme později.

13Pod projektem rozumíme soubory, které tvoří program, spolu nastaveními překladače, která se použijí pro překlad jednotlivých zdrojových souborů, pro jejich sestavení do spustitelného souboru a s dalšími informacemi.

14Toto prostředí si lze stáhnout buď spolu s překladačem C++ (GCC verze 4.9.2), nebo bez něj. Ve druhém případě se předpokládá, že máte na svém počítači již nějaký překladač k dispozici.

2První program

Stalo se zvykem, že učebnice jazyků C aC++ začínají programem, který vypíše do konzolového okna pozdrav askončí. Imy se této tradice přidržíme, neboť nám umožní seznámit se se základními operacemi při vytváření programu. Přitom si předvedeme jak práci bez vývojového prostředí, tak sjeho použitím. Může se vám sice zdát, že spouštění překladače zpříkazové řádky je záležitost beznadějně zastaralá, nám ale umožní ukázat si, co se vlastně děje, jaké soubory vznikají aněkteré další souvislosti.

Naším cílem je napsat program, který vypíše do konzolového okna následující text:

Nazdar, lidi!

Pak přejde na novou řádku askončí. Uživatel bude tento program spouštět zpříkazové řádky (půjde tedy otzv. konzolovou aplikaci).

2.1Bez použití vývojového prostředí

Nejprve vytvoříme zdrojový kód programu. Ten pak přeložíme aspustíme.

2.1.1Zdrojový kód

Kvytvoření zdrojového kódu našeho programu použijeme libovolný editor, který umí uložit prostý text. Pod Windows docela dobře poslouží Poznámkový blok, pod Linuxem například editor nano, vi nebo jiný. Vtomto editoru vytvoříme soubor obsahující následující text:

// První program vC++

#include <iostream>

int main()

{

std::cout << "Nazdar, lidi" << std::endl;

return 0;

}

Tento soubor pojmenujeme prvni.cpp auložíme ho do zvoleného adresáře – například TEMP.

■Pozor, při opisování je třeba dodržet „velikost“ písmen!

■Ve druhém řádku je slovo iostream uzavřeno do závorek tvořených znaky „menší než a„větší než“.

2.1.2Překlad aspuštění

Nyní je třeba program přeložit. Vkonzolovém okně přejdeme do adresáře, vněmž je program uložen. Pracujeme-li pod Windows, napíšeme zde příkaz:

g++ -oprvni.exe -Wall prvni.cpp

Vprostředí Linuxu se bude tento příkaz lišit jen nepatrně – spustitelný soubor nebude mít příponu .exe:

g++ -oprvni -Wall

Je-li vše vpořádku, nevypíše tento program do konzolového okna nic. Přeloží asestaví náš program avadresáři se zdrojovým textem přibude soubor prvni (pod Windows prvni.exe).[15] Vytvořený program spustíme příkazem:

prvni

Program pak vypíše:

Nazdar, lidi

Obrázek 2.1 ukazuje přechod do adresáře programu, překlad aspuštění vkonzolovém okně Windows 7.

Obrázek 2.1 Překlad našeho prvního programu zpříkazové řádky ajeho spuštění

Příkaz pro překlad

Příkaz pro překlad začíná jménem volaného programu – vnašem případě g++. Pak následují tzv. volby (anglicky options, někdy nazývané také parametry). Volby začínají jednou nebo dvěma pomlčkami:

■Volba -ourčuje jméno přeloženého programu – to je vnašem případě první.exe. Toto jméno oddělíme od symbolu volby mezerou. Kdybychom tuto volbu neuvedli, jmenoval by se výsledný program a.exe.

■Volba –Wall říká, že chceme, aby překladač vypisoval nejen zprávy ochybách, ale itzv. varování (ktomu, co to znamená, se brzy vrátíme).

Za volbami následuje seznam překládaných souborů. Zatím zde uvádíme jediný, prvni.cpp; až jich bude více, oddělíme je mezi sebou mezerou.

Jiné překladače

Používáte-li jiný překladač, bude se struktura příkazu pro překlad stejná, příkaz se však bude lišit – kromě jména překladače – ivpoužitých volbách. Ty mohou začínat pomlčkou nebo lomítkem. Obvykle platí, že když neuvedete jméno výstupního souboru, bude stejné jako jméno prvního zpřekládaných souborů. Ostatní překladače také typicky vytvářejí relativní soubory aponechávají je na disku.

Například příkaz pro překlad našeho prvního programu překladačem Visual C++ bude mít tvar:

cl /Wall prvni.cpp

Jméno tohoto překladače je cl.exe avolba /Wall má stejný význam jako volba -Wall překladače g++. Vadresáři našeho programu najdeme jednak relativní soubor prvni.obj, jednak spustitelný soubor prvni.exe.

2.1.3Když se něco nezdaří

Podívejme se na nejobvyklejší problémy, snimiž se můžeme při překladu programu setkat.

Počítač neví, kde najde překladač

Jestliže po zadání příkazu pro překlad počítač vypíše například:

g++ není názvem vnitřního ani vnějšího příkazu,

spustitelného programu nebo dávkového souboru.

nebo

bad command or filename

či jinou zprávu, zníž vyplývá, že počítač neví, co po něm chceme, znamená to, že nenašel překladač. (Přesný text zprávy závisí na verzi ajazykové mutaci operačního systému, pod nímž pracujeme, význam je ale stále týž.)

Pak je třeba uložit cestu kpřekladači do systémové proměnné PATH.

Pracujeme-li pod Windows aje-li překladač g++ instalován například vadresáři C:\Program Files\MinGW32, použijeme příkaz:

SET PATH=%PATH%;“C:\Program Files\MinGW32\bin“

Protože jméno jednoho zadresářů vcestě kpřekladači obsahuje mezeru, museli jsme celou tuto cestu zapsat do uvozovek.

Poznamenejme, že součástí instalace mnoha překladačů je dávkový soubor, jehož spuštěním tuto cestu nastavíme. Vpřípadě g++ instalovaného pod Windows jako součást balíku MinGW32 (ať už samostatně nebo vrámci prostředí Code::Blocks) se tento soubor jmenuje mingwvars.bat anajdeme ho vadresáři sinstalací tohoto nástroje.[16]

Vpřípadě Visual C++ se podobný soubor jmenuje vcvarsall.bat anajdeme ho vpodadresáři VC adresáře sinstalací Visual Studia. Kromě cesty kpřekladači mění iřadu dalších nastavení nezbytných pro spouštění překladače zpříkazové řádky.

Jestliže jste překladač g++ instalovali vprostředí Linuxu pomocí balíčkovací služby, neměli byste na problém scestou narazit.

Syntaktická chyba

Jestliže překladač vypíše zprávu, vníž je za jménem překládaného souboru slovo error, znamená to, že vprogramu je syntaktická chyba – program není zapsán podle pravidel jazyka C++, takže ho překladač neumí přeložit.

Zkusme například vynechat středník na koncišesté řádky našeho programu (počítáme iprázdné řádky). Dostaneme výstup:

prvni.cpp: In function 'int main()':

prvni.cpp:7:5: error: expected ';' before 'return'

Poznamenejme, že vněkterých prostředích dostaneme podobnou zprávu česky. První řádka této zprávy nás informuje, že překladač narazil na problém vsouboru prvni.cpp ve funkci main(). Ve druhé řádce této zprávy říká, že vsedmé řádce programu avpátém sloupci očekával středník před slovem return. (Středník sice chybí už všesté řádce, ale překladač na to přišel, až když začal zpracovávat sedmou řádku.)

Chybová zpráva, kterou vypíší jiné překladače, bude velmi podobná.

Překladač se po nalezení chyby pokusí zkontrolovat izbytek zdrojového souboru, vněmž chybu našel, ale nevytvoří přeložený program.

Varování

Jestliže překladač najde ve zdrojovém programu něco, čemu nerozumí aco nedokáže přeložit, ohlásí chybu asoubor nepřeloží – to už známe. Kromě chyb ovšem hlásí překladače jazyků C aC++ také varování, tedy upozornění na konstrukce, jež sice nejsou syntakticky chybné, překladač jim rozumí aumí je přeložit, ale mohou mít jiný význam, než si programátor myslí. Program svarováními překladač přeloží.

Program bychom vždy měli překládat snastaveným výstupem varování, tedy svolbou –Wall upřekladače g++ aujiných překladačů svolbou spodobným významem. Varováním bychom měli věnovat stejnou pozornost jako chybám aměli bychom se přesvědčit, že neznamenají chybu. (Mé vlastní zkušenosti mne přesvědčily, že více než 90 % varování ve skutečnosti chybu znamenalo.)

Překlad správně napsaného programu by neměl obsahovat ani jedno varování.

2.2Používáme vývojové prostředí

Vytváření programu bez integrovaného vývojového prostředí aspouštění překladače zpříkazové řádky je spíše netypické, aproto se nyní podíváme, jak týž program vytvoříme, přeložíme aspustíme vintegrovaném vývojovém prostředí (IDE) nástroje Code::Blocs (CB).

2.2.1Vytváříme projekt

Nejprve spustíme IDE – například pomocí ikony na ploše. Po úvodní obrazovce uvidíme hlavní okno tohoto programu (viz obrázek 2.2).

Obrázek 2.2 Okno integrovaného vývojového prostředí Code::Blocs po spuštění

Největší část tohoto okna zabírá podokno editoru, vněmž budeme vytvářet zdrojový text programu. Než stím ale začneme, musíme vytvořit projekt azařadit do něj zdrojový soubor. Vhlavní nabídce zvolíme položku File, vnabídce, která se tím rozvine, zvolíme New avpodřízené nabídce pak příkaz Project…. (Takovouto posloupnost příkazů znabídky budeme zapisovat File | New | Project) Tím vyvoláme dialogové okno sikonami různých typů projektů (viz obrázek 2.3). Vněm označíme typ Console application (čtvrtá položka vprvní řádce) astiskneme tlačítko Go.

Obrázek 2.3 Dialog pro volbu typu projektu

Objeví se okno průvodce vytvořením projektu, vněmž nám prostředí oznámí, že jsme si zvolili konzolovou aplikaci; stiskneme tlačítko Next>. Objeví se další okno, vněmž si můžeme vybrat, zda chceme používat jazyk C nebo C++. Ponecháme nabídnuté C++ astiskneme opět tlačítko Next>. Tentokrát se objeví okno, vjehož vprvním vstupním poli (Project title) zadáme jméno projektu; zvolíme opět jméno prvni. Ve druhém vstupním poli tohoto dialogového okna zvolíme adresář, vněmž chceme svůj projekt uložit. Ve třetím poli nám IDE nabídne jméno souboru spopisem projektu – vnašem případě prvni.cbp, ave čtvrtém toto jméno iscestou (viz obrázek 2.4 vlevo). Po zadání jména projektu ajeho adresáře stiskneme opět tlačítko Next>.

Objeví se poslední okno tohoto průvodce, vněmž můžeme zvolit překladač, který chceme použít; ponecháme nabídnutou možnost GNU GCC Compiler, neboť jiný překladač nejspíš stejně nemáme, aponecháme zaškrtnuté možnosti Create „Debug“ configuration aCreate „Release“ configuration. Tím říkáme, že chceme jak ladicí, tak iostrou verzi přeloženého programu. Ktomu sevrátíme vnásledující poznámce. Nyní stiskneme tlačítko Finish aprostředí vytvoří náš projekt.

Obrázek 2.4 Dialog pro určení jména aadresáře projektu

Vlevé části okna IDE je podokno nadepsané Management (správa). Vněm klepneme na záložku Project, není-li už vybrána, auvidíme strom projektu. Zatím je sbalený, je vidět pouze kořen označující pracovní prostor (Workspace) apodřízený uzel označující náš projekt prvni. Klepnutím na + se tento uzel rozbalí auvidíme podřízený uzel Sources označující zdrojové soubory; jeho rozbalením se dostaneme ksouboru main.cpp, jedinému zdrojovému souboru našeho programu. (CB nám nedalo možnost určit jeho jméno.) Po poklepání na jméno tohoto souboru se zobrazí jeho obsah vpodokně editoru (viz obrázek 2.5).

Obrázek 2.5 Integrované vývojové prostředí CB se zdrojovým textem programu ase zprávou oúspěšném překladu

Program přeložený vladicí konfiguraci obsahuje dodatečné informace, které usnadňují ladění, tedy zjišťování, proč program dělá něco jiného než má. Vostré verzi tyto dodatečné informace nejsou, takže spustitelný soubor je menší aprogram běží rychleji, nelze ho ale použít sladicími nástroji. Oladění programu budeme hovořit voddílu 4.5.

2.2.2Píšeme program

Nyní můžeme do okna editoru napsat svůj první program. Ovládání tohoto editoru vsobě neskrývá žádné problémy. Editor označuje různé součásti zdrojového textu různými barvami; důvod avýznam pochopíme později. Po levé straně podokna editoru jsou zobrazena čísla řádek asymboly + nebo – naznačující, že některé části zdrojového textu můžeme skrýt (sbalit), nebo zase zobrazit (rozbalit).

Po napsání uložíme zdrojový text; vedle toho ovšem musíme uložit isoubor spopisem projektu adalší pomocné soubory, které si CB vytváří; ktomu použijeme buď příkaz File | Save all files znabídky, nebo tlačítko Save all files na panelu nástrojů, nebo klávesovou zkratku CTRL+SHIFT+S.

Budeme-li chtít uložit jen zdrojový text vjednom souboru, použijeme buď příkaz File | Save file znabídky, nebo stiskneme tlačítko Save na panelu nástrojů pod nabídkou (třetí tlačítko zleva), nebo použijeme klávesovou zkratku CTRL+S.

2.2.3Překládáme program

Naším dalším úkolem je napsaný program přeložit asestavit. Ktomu použijeme buď příkaz znabídky Build | Build, tlačítko sozubeným kolem na panelu nástrojů, nebo klávesovou zkratku CTRL+F9. Je-li vše vpořádku, otevře se ve spodní části okna CB podokno nadepsané Build log (deník překladu) avněm se zobrazí zpráva oprůběhu překladu aoumístění vytvořených souborů (viz obrázek 2.5).

Jestliže bude zdrojový text obsahovat nějakou chybu (například opět vynecháme středník na konci páté řádky), objeví se zde podobná chybová zpráva jako při překladu zpříkazové řádky, navíc však bude končit sdělením:

Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s))

Toto sdělení říká, že se překlad asestavování nepodařilo aže překladač našel 1 chybu, ale že pro nás nemá žádné varování; dále se dozvíme, kolik času překlad zabral.

Poklepáním na chybovou zprávu se otevře soubor se zdrojovým textem (pokud už není otevřen) aprostředí vyznačí chybu červenou značkou učísla řádky.

2.2.4Soubory projektu

Podívejme se nyní do adresáře, kde je projekt umístěn; jestliže jsme předepsali například adresář K:\ TEMP, vstupme do něj azobrazme si jeho obsah pomocí vhodného nástroje. Zjistíme, že CB zde vytvořilo podadresář prvni (jméno se shoduje se jménem projektu). Vněm najdeme soubor prvni.cbp spopisem projektu azdrojový soubor main.cpp. Vedle toho jsou zde ještě podadresáře bin aobj.

Podadresář bin obsahuje podadresář Debug avněm najdeme po úspěšném překladu asestavení spustitelný soubor prvni.exe.

Podadresář obj obsahuje také podadresář Debug; vněm najdeme po úspěšném překladu objektový soubor main.o.

2.2.5Spouštíme program zIDE CB

Po úspěšném překladu asestavení si budeme chtít program vyzkoušet. Můžeme ho samozřejmě spustit zpříkazové řádky, ale CB nám nabízí imožnost spustit ho přímo zIDE. Ktomu použijeme příkaz Build | Run znabídky nebo tlačítko Run na panelu nástrojů (je označeno zelenou šipkou). Můžeme také použít klávesovou zkratku F9. Otevře se konzolové okno, vněmž uvidíme výstup našeho programu, adále sdělení, že proces vrátil hodnotu 0 (co to znamená, poznáme vnásledujícím oddílu) ajak dlouho trval jeho běh. Výstup končí výzvou Press any key to continue, tedy „pokračujte stisknutím libovolné klávesy“. Po stisknutí libovolné klávesy se toto okno uzavře. Poznamenejme, že poslední dvě zprávy připojilo prostředí CB.

Konzolové okno po doběhnutí našeho programu ukazuje obrázek 2.6.

Obrázek 2.6 Konzolové okno svýstupem našeho programu po spuštění zIDE

2.3Co jsme naprogramovali

Už víme, jak program zapsat, přeložit, sestavit aspustit, je tedy nejvyšší čas vysvětlit si, co znamenají jeho jednotlivé části. Pro pohodlí si zde jeho zdrojový text zopakujeme.

// První program vC++

#include <iostream>

int main()

{

std::cout << "Nazdar, lidi" << std::endl;

return 0;

}

2.3.1Komentář

Na první řádce tohoto programu vidíte tzv. komentář. To je část programu, která nemá pro překladač vůbec žádný význam, nijak neovlivní chod přeloženého programu. Komentáře slouží programátorům, kteří si do nich zapisují poznámky ovýznamu různých částí programu. (Komentáře odstraní zprogramu před vlastním překladem preprocesor.)

Komentář vjazyce C++ začíná dvěma lomítky zapsanými bezprostředně za sebou akončí na konci řádky.

Někdy ovšem potřebujeme komentář vložit doprostřed řádky, nebo naopak potřebujeme komentář, který zabírá několik řádků za sebou. Je to možné: komentář může také začínat dvojicí znaků \* zapsaných bezprostředně za sebou akončit dvojicí */. Vše, co je mezi těmito „komentářovými závorkami“, bude překladač ignorovat.

Příklady takto zapsaných komentářů uvidíme dále. Poznamenejme, že takto zapsané komentáře nelze vnořovat do sebe, tedy že uvnitř jednoho komentáře začínajícího znaky \* nesmí být další komentář začínající \*.

Možná vám budou komentáře zpočátku připadat zbytečné. Svému programu přece rozumíte, vždyť jste ho sami napsali. Jenže programy – svýjimkou školních – mohou mít dlouhý život azákazníci vyžadují, abyste vnich opravili chyby nebo abyste do nich přidali nové možnosti. Když po čase ke svému programu vrátíte, budou pro vás dobře napsané komentáře představovat neocenitelnou pomoc.

Mezi programátory je obvyklé, že komentáře píší buď anglicky (kdyby to náhodou četl někdo cizí...) nebo alespoň „cesky“ (tedy bez háčků ačárek). Důvod je jednoduchý: Asi víte, že vrůzných prostředích se můžete setkat srůznými způsoby kódování češtiny, apři přenosu programu zjednoho prostředí do jiného mohou vzniknout problémy.[17]

Vnaší knize budeme ovšem psát komentáře důsledně česky, to znamená isdiakritickými znaménky. Izde je důvod jednoduchý: jak vidite zteto kratke veticky, cesky psane komentare byvaji spatne srozumitelne. Nebudeme si tedy přidělávat zbytečnou práci sluštěním „cestiny“.

2.3.2Hlavičkový soubor

Překladač jazyka C++ nezná nic jiného než jazyk C++. To znamená, že nezná ani nástroje, které jsou vknihovnách akteré ve svém programu používáme. Například vnašem programu jsou to nástroje označené jmény std::cout astd::endl. Chceme-li takovéto nástroje použít, musíme snimi překladač nějakým způsobem seznámit; jinak řečeno, musíme je před použitím deklarovat.

Ovšem ve skutečném programu by takových deklaraci muselo být velmi mnoho, aproto pro nás tvůrci překladačů připravili tzv. hlavičkové soubory (anglicky header file), které již tyto deklarace obsahují. Nástroje pro vstupní avýstupní operace, mezi nimi istd::cout astd::endl, jsou deklarovány vhlavičkovém souboru iostream.[18]

Příkaz na druhé řádce našeho programu říká preprocesoru, aby na toto místo programu vložil ještě před vlastním překladem obsah uvedeného hlavičkového souboru. Skládá se zdirektivy #include, za niž následuje jméno vkládaného souboru uzavřené vlomených závorkách (tyto závorky tvoří znaky „menší než“ a„větší než“).

Časem se seznámíme sřadou dalších hlavičkových souborů anaučíme se je isami vytvářet. Poznamenejme, že standardní hlavičkové soubory jsou typicky uloženy vpodadresáři include adresáře sinstalací překladače.

2.3.3Funkce main()

Vprvní kapitole jsme si řekli, že pod pojmem funkce rozumíme vC++ naprogramovaný dílčí algoritmus. To znamená, že každý program vC++ musí obsahovat alespoň jednu funkci. Tato „povinná“ funkce se jmenuje main().[19] Její definice, tedy popis toho, co má tato funkce dělat, vnašem programu začíná na čtvrté řádce apokračuje do konce souboru. (Místo definice říkáme také definiční deklarace.)

Definice funkce se skládá zhlavičky atěla; tělo funkce se skládá zpříkazů uzavřených do složených závorek. Běh programu vC++ začíná vždy prvním příkazem funkce main() askončí, když skončí funkce main().

2.3.4Hlavička funkce main()

Hlavička funkce určuje jméno (identifikátor) funkce, typ jejího výsledku aparametry (hodnoty, které tato funkce zpracuje, znichž vypočte výsledek). Hlavička funkce main() má tvar:

int main()

aříká, že tato funkce se jmenuje main, její výsledek je typu int (takto se vC++ označuje datový typ používaný pro celá čísla) anemá žádné parametry (to říkají prázdné závorky za jménem funkce).

2.3.5Tělo funkce main()

Tělo funkce popisuje, co má tato funkce dělat – jinými slovy obsahuje příkazy, které provádějí algoritmus této funkce. Tělo funkce je vždy uzavřeno do složených závorek { a} askládá se zpříkazů, které říkají, co má program dělat.

2.3.6Výstup textu

Úkolem našeho programu je vypsat pozdrav do konzolového okna. Kvypisování údajů do tohoto okna slouží tzv. standardní výstupní proud, který se jmenuje std::cout aje kdispozici vknihovně jazyka C++. Jde oinstanci jistého objektového typu, který je také součástí knihovny – ale otom si povíme později. Hodnotu, kterou chceme vypsat, vložíme do tohoto proudu pomocí operátoru << (dva znaky „menší než“ zapsané bezprostředně za sebou). Text (říkáme mu řetězcový literál), který chceme vypsat, uzavřeme do uvozovek. To znamená, že konstrukce:

std::cout << "Nazdar, lidi!"

představuje příkaz pro vypsání uvedeného pozdravu. Program má ovšem ještě jeden úkol, ato po vypsání pozdravu přejít na novou řádku. Toho jsme zde dosáhli tím, že jsme do proudu std::cout vložili manipulátor std::endl. To znamená, že příkaz:

std::cout << "Nazdar, lidi" << std::endl;

znamená „vypiš zadaný text apak přejdi na novou řádku“. Jednotlivé položky se vypisují vpořadí, vjakém je do proudu vložíme.

Doplňme, že řetězcový literál je vpaměti uložen jako pole,[20] jehož prvky obsahují jednotlivé znaky; za poslední znak je připojen speciální znak říkající „zde tento text končí“.

2.3.7Výsledek funkce main()

Pravidla jazyka C++ říkají, že funkce main()vypočte hodnotu typu int, tedy celé číslo. Říkáme také, že tato funkce vrátí hodnotu typu int, nebo že tato funkce je typu int.

Hodnota vypočtená (vrácená) funkcí main() představuje tzv. kód ukončení programu (exit code). Hodnota 0 typicky znamená, že program proběhl bez problémů, nenulové hodnoty zpravidla představují kódy chyb, knimž došlo. Poznamenejme, že prostředí CB tuto hodnotu vypíše po ukončení běhu programu vkonzolovém okně ve zprávě Process returned..., kterou připojí vkonzolovém okně za výstup programu.

Hodnotu, jež je výsledkem funkce (hodnotu, kterou funkce vrátí) určíme příkazem, který se skládá za slova return, za nímž následuje hodnota výsledku. To znamená, že příkaz:

return 0;

říká, že výsledkem funkce main() je hodnota 0, tedy že program skončil bez chyb.

Později uvidíme, že příkaz return znamená ještě „ukonči provádění této funkce“; vnašem případě to ovšem nemá význam, protože jde oposlední příkaz vtěle funkce main().

2.3.8Středník

Všimněte si, že oba příkazy vtěle funkce main() jsou ukončeny středníkem. Ukončovací středník je povinnou součástí některých příkazů vjazyce C++ anelze ho vynechat, ikdyž nám bude připadat zbytečný. Není to oddělovač příkazů, jako vněkterých jiných programovacích jazycích.

2.3.9Jméno apříjmení (jmenné prostory)

Při vývoji rozsáhlých programů se často vedle standardní knihovny používají také knihovny třetích stran, zaměřené na některé speciální oblasti. Přitom se může stát, že dvě knihovny budou obsahovat funkci, proměnnou nebo jinou entitu se stejným jménem, ikdyž sjiným významem. Aby bylo možné předcházet takovýmto konfliktům jmen, dovoluje jazyk C++ připojit ke jménům entit něco jako příjmení. Jinak řečeno, jména vprogramech, knihovnách apod. mohou být deklarována vtzv. jmenných prostorech (namespace). Téměř všechna jména ze standardní knihovny jazyka C++ jsou deklarována ve jmenném prostoru std.

Jméno jmenného prostoru připojujeme před jméno entity operátorem ::, který se skládá ze dvou dvojteček zapsaných bezprostředně za sebou (aproto se mu občas říká čtyřtečka).

To znamená, že například standardní výstupní proud se ve skutečnosti jmenuje pouze cout amanipulátor způsobující přechod na novou řádku se jmenuje endl; vnašem programu jsme kněmu ovšem museli připojit ijméno jmenného prostoru, vněmž jsou deklarovány.

Připojování tohoto „příjmení“ ke všem jménům zknihovny je ovšem poněkud nepříjemné, aproto nám nabízí jazyk C++ několik možností, jak se tomu vpřípadě, že nehrozí konflikt jmen, vyhnout.

Jednou znich je oznámit překladači, že uvybraných jmen budeme toto „příjmení“ vynechávat. Ktomu použijeme deklaraci ve tvaru:[21]

using jméno-prostoru :: jméno-entity ;

kde jméno-prostoru je jméno jmenného prostoru, vněmž je deklarována entita určená jménem-entity. Pak můžeme používat jméno-entity samotné. To znamená, že náš program můžeme přepsat do tvaru:

#include <iostream>

using std::cout;

using std::endl;

int main()

{

cout << "Nazdar,lidi!" << endl;

return 0;

}

Bude fungovat naprosto stejně jako naše předchozí verze.

Jinou možností je oznámit překladači, že jméno daného jmenného prostoru budeme vynechávat uvšech entit, které jsou vněm deklarovány. Ktomu nám poslouží deklarace

using namespace jméno-prostoru ;

kde jméno-prostoru je opět jméno jmenného prostoru, které chceme vynechávat. Náš program tedy můžeme také přepsat do tvaru:

#include <iostream>

using namespace std;

int main()

{

cout << "Nazdar,lidi!" << endl;

return 0;

}

Této možnosti dáváme přednost, používáme-li více entit zdaného jmenného prostoru.

Jméno jmenného prostoru můžeme ke jménu entity připojit, ikdyž předtím překladači řekneme pomocí jedné zdeklarací using, že ho budeme vynechávat. Vpřípadě, že opravdu hrozí konflikt jmen, je to nezbytné.

2.3.10Jak zapisujeme zdrojový program

Svůj první program jsme úspěšně přeložili aspustili, apokud jsme vše opsali přesně podle uvedené předlohy, nenarazili jsme na žádné problémy. Nicméně požadavky na zápis programů nejsou tak striktní; prozatím vystačíme sněkolika pravidly.[22]

Program vC++ se skládá ze symbolů. To jsou například jména proměnných, funkcí apod., vyhrazená slova označující součásti příkazů, datové typy adalší. Dále sem patří operátory, jako je +, ++, <= atd. Symbol nesmíme rozdělit mezerou ani jiným způsobem (přechodem na novou řádku, komentářem), musí být zapsán jako jeden celek. Na druhé straně mezi dvěma jmény nebo mezi jménem avyhrazeným slovem musí být alespoň jedna mezera.

Direktiva preprocesoru musí být vždy na samostatné řádce. Všude, kde smíme udělat mezeru, jich můžeme udělit iněkolik; můžeme tam použít ipřechod na novou řádku nebo komentář. To znamená, že nesmíme napsat například:

intmain()

neboť symboly int amain musí být odděleny alespoň jednou mezerou – jinak by je překladač pokládal za jeden symbol azlobil by se, že neví, co znamená. Nemůžeme také napsat:

int ma in()

protože symbol main nesmíme rozdělit – překladač by zde viděl dva symboly, ma ain.

Na druhé straně můžeme napsat:

int main ( )

neboť mezi symbolem main alevou závorkou může být mezera, stejně jako mezi závorkami.

To znamená, že náš první program můžeme zapsat například ve tvaru:

#include <iostream>

using namespace std;int/*první program*/main(){cout<<"Nazdar,lidi!"

<<endl;return 0 ;}

Direktiva preprocesoru musí, jak víme, být na samostatné řádce, ale zbytek programu můžeme napsat celý na jednu řádku, pokud se nám tam vejde. Jako oddělovač mezi slovy int amain jsme zde použili komentář – ito lze, ikdyž to obvykle nevede kpříliš přehlednému programu. Za závorkou { může, ale nemusí být mezera nebo přechod na novou řádku, podobně například mezi znakem 0 astředníkem ukončujícím příkaz return, nebo mezi tímto středníkem asloženou závorkou }.

Je ale jasné, že takto zapsaný program je pro člověka nepřehledný.

Běžné konvence

Obvykle dodržujeme při psaní programu následující konvence:

■Složenou závorku } uzavírající tělo funkce umísťujeme pod odpovídající složenou závorku {, jež tělo funkce otevírá. Podobně umísťujeme pod sebe isložené závorky, jež jsou součástí některých příkazů, které poznáme vnásledujících kapitolách.

Table of Contents

Předmluva

Co v této knize najdete

Nástroje

Terminologie

Příklady

Poděkování

1 Než začneme

1.1 Počítač

1.1.1 Operační paměť

1.1.2 Soustava SI, bity a bajty

1.2 Datové typy a proměnné

1.3 Programy a programovací jazyky

1.3.1 Jazyk C++

1.3.2 Asembler

1.4 Operační systém

1.5 Program a algoritmus

1.5.1 Metoda shora dolů

1.5.2 Metoda zdola nahoru

1.6 Objekty a třídy

1.6.1 Zapouzdření

Bod jako objekt

Třída, datová složka

Metoda

Ukrývání implementace

Zapouzdření

Objektový program

Modelovací jazyk UML

Skládání objektů

1.6.2 Dědění

1.6.3 Polymorfizmus

Virtuální metoda

Abstraktní třída

Dědění versus skládání

1.6.4 Objektové a neobjektové programování

1.6.5 Poznámka k terminologii

1.7 Céčko se dvěma plusy

1.7.1 Vývoj C++

1.7.2 Dvě úrovně znalostí C++

1.7.3 Vývojové nástroje

1.7.4 Kde získat potřebné nástroje

1.7.5 Co budeme používat

2 První program

2.1 Bez použití vývojového prostředí

2.1.1 Zdrojový kód

2.1.2 Překlad a spuštění

Příkaz pro překlad

Jiné překladače

2.1.3 Když se něco nezdaří

Počítač neví, kde najde překladač

Syntaktická chyba

Varování

2.2 Používáme vývojové prostředí

2.2.1 Vytváříme projekt

2.2.2 Píšeme program

2.2.3 Překládáme program

2.2.4 Soubory projektu

2.2.5 Spouštíme program z IDE CB

2.3 Co jsme naprogramovali

2.3.1 Komentář

2.3.2 Hlavičkový soubor

2.3.3 Funkce main()

2.3.4 Hlavička funkce main()

2.3.5 Tělo funkce main()

2.3.6 Výstup textu

2.3.7 Výsledek funkce main()

2.3.8 Středník

2.3.9 Jméno a příjmení (jmenné prostory)

2.3.10 Jak zapisujeme zdrojový program

Běžné konvence