+ All Categories
Home > Documents > Seminar Cpp S

Seminar Cpp S

Date post: 04-Apr-2015
Category:
Upload: ivan-merka
View: 89 times
Download: 0 times
Share this document with a friend
55
FAKULTA ELEKTROTECHNIKY A KOMUNIKAČNÍCH TECHNOLOGIÍ VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ Seminář C++ Garant předmětu: Ing.Pavel Fiala, Ph.D. Autor textu: Ing. Pavel Fiala, Ph.D. Brno 1.2.2005
Transcript
Page 1: Seminar Cpp S

FAKULTA ELEKTROTECHNIKY A KOMUNIKAČNÍCH TECHNOLOGIÍ VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ

Seminář C++

Garant předmětu:

Ing.Pavel Fiala, Ph.D.

Autor textu: Ing. Pavel Fiala, Ph.D.

Brno 1.2.2005

Page 2: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Obsah 1 ÚVOD ................................................................................................................................4

1.1 ZÁKLADNÍ POJMY A UJEDNÁNÍ.....................................................................................4 1.2 VLASTNOSTI C/C++ ....................................................................................................6 1.3 ZÁSADY, SMĚRNICE ANSI...........................................................................................8 1.4 OBJEKTOVĚ ORIENTOVANÉ PROGRAMOVÁNÍ ...............................................................9 1.5 PROGRAM- OPERAČNÍ SYSTÉM.....................................................................................9 1.6 SESTAVENÍ PROGRAMU..............................................................................................10 1.7 ZÁKLADNÍ PRVKY ZÁPISU BLOKOVÉHO SCHÉMATU ...................................................12 1.8 ALGORITMY...............................................................................................................13 1.9 KONTROLNÍ OTÁZKY .................................................................................................20 1.10 ÚKOLY ......................................................................................................................20

2 NĚKTERÉ ROZDÍLY C A C++...................................................................................20 2.1 KLÍČOVÁ SLOVA C++ ................................................................................................21 2.2 ÚKOLY ......................................................................................................................23

3 TŘÍDY .............................................................................................................................23 3.1 DATOVÉ SLOŽKY .......................................................................................................24 3.2 ČLENSKÉ FUNKCE- METODY ......................................................................................26 3.3 UKAZATEL THIS ........................................................................................................31 3.4 AGREGÁTY ................................................................................................................31 3.5 OBLASTI PLATNOSTI A DOSAŽITELNOSTI IDENTIFIKÁTORŮ ........................................32 3.6 PROSTORY JMEN ........................................................................................................32 3.7 PAMĚŤOVÉ TŘÍDY ......................................................................................................34 3.8 KONTROLNÍ OTÁZKY .................................................................................................34 3.9 ÚKOLY ......................................................................................................................34

4 OBJEKTY .......................................................................................................................34

4.1 PŘIŘAZOVÁNÍ OBJEKTŮ .............................................................................................35 4.2 PŘEDÁVÁNÍ OBJEKTŮ FUNKCÍM .................................................................................35 4.3 VRÁCENÍ OBJEKTŮ FUNKCEMI ...................................................................................36 4.4 ÚKOLY ......................................................................................................................37

5 OPERÁTORY.................................................................................................................37

5.1 PŘEHLED OPERÁTORŮ................................................................................................37 5.2 POPIS, UŽITÍ OPERÁTORŮ ...........................................................................................39 5.3 PŘETĚŽOVÁNÍ OPERÁTORŮ ........................................................................................42 5.4 ÚKOLY ......................................................................................................................43

6 DĚDIČNOST ..................................................................................................................44 6.1 SYNTAKTICKÝ ZÁPIS..................................................................................................44 6.2 PŘÍSTUPY V DĚDIČNOSTI............................................................................................44 6.3 ÚKOLY ......................................................................................................................47

7 POLYMORFISMUS ......................................................................................................47

7.1 ÚKOLY ......................................................................................................................48

8 PŘETĚŽOVÁNÍ FUNKCÍ ............................................................................................48 8.1 PŘETĚŽOVÁNÍ KONSTRUKTORŮ .................................................................................49

str. 2

Page 3: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

8.2 ANACHRONISMUS PŘETĚŽOVÁNÍ ...............................................................................50 8.3 PŘETĚŽOVÁNÍ A NEJEDNOZNAČNOST.........................................................................50 8.4 ÚKOLY ......................................................................................................................51

9 ŠABLONY FUNKCÍ A TŘÍD .......................................................................................51 9.1 PARAMETRY ŠABLON.................................................................................................51 9.2 ŠABLONY FUNKCÍ ......................................................................................................52 9.3 ŠABLONY OBJEKTOVÝCH TYPŮ ..................................................................................52 9.4 ÚKOLY ......................................................................................................................53

10 OBSLUHA VÝJIMEK...............................................................................................53 10.1 ÚKOLY ......................................................................................................................54

11 ZÁVĚR ........................................................................................................................54 11.1 LITERATURA..............................................................................................................55

str. 3

Page 4: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

1 Úvod

Předmět Seminář C++ je vyučován v letním semestru 2. ročníku bakalářského studia FEKT VUT v Brně. Předmět předpokládá úspěšné absolvování kurzů Počítače a programování 1 a Počítače a programování 2. Volně navazuje na znalosti získané v těchto kurzech a bude používat také prostředí Borland C++ Builder 6.0.

Kurz si klade za cíl rozšířit základní znalosti jazyka C a doplnit o prvky C++ . Usiluje o hlubší poznatky a dovednosti cestou praktických zkušeností. Ty získá při sestavování zadaných programů a jejich odlaďování. Proto je volena forma semináře s nachystanými neřešenými úkoly a jejich realizace pod odborným dohledem a vedením student bude dále budovat své programátorské schopnosti. Student se tak velmi efektivně a individuálně rozvíjí. Může dosáhnout dobrých výsledků a získat návyky vedoucí k samostatnému vzdělávání v oblastech nejen tvorby počítačových programů.

Kurzy Počítače a programování 1 a Počítače a programování 2 byly z velké části zaměřeny na koncepci událostmi řízeného programování, jeho úvod a procvičení s prvky API. Seminář C++ naopak bude budovat klasicky orientované programování- tvorba funkcí, zařazení do událostmi řízeného programu. Bude dbát na efektivní využití prvků C/C++, pro tvorbu krátkých a rychlých programů se všemi výhodami jazyka C++. Nelze v přiděleném čase pro seminář zvládnout špičkově problematiku C++, ale je zde prostor pro vybudování základních programátorských návyků a potlačení programátorských zlozvyků. V programování platí mnoho základních pravidel, jak se stát programátorem, a mezi ně patří: „nejdříve mysli, pak piš“, „programátorem se stáváme podle počtu dobře napsaných vlastních programů, nikoliv opsaných“, „programátor se pozná podle algoritmu“ atd. V kurzu se budeme snažit psát takové programy, které nezávisí na platformě, na které se budou provozovat.

Následující text lze označit přeneseně za kostru pravidel C++, mnohdy „děravou“. Existuje několik přístupů k výuce programování. Jedna cesta je založena na dodání budoucímu programátoru veškerých informací na stůl a stačí začít programovat. Jiná cesta, která si myslím je bližší skutečnému životu, je taková, že programátor získá pouze základní informace o jazyku, základní příklady použití. Student sám si musí najít nebo získat doplňující informace, samozřejmě musí mít velmi dobré základny algoritmizace. Touto cestou se orientuje kurz Seminář C++.

1.1 Základní pojmy a ujednání

Programátoři mezi sebou komunikují specifickým jazykem. Abychom tomuto jazyku porozuměli, seznámíme se nyní společně s pojmy, s nimiž se budeme setkávat.

Abstrakce pojem je převážně používán v souvislosti s implementací tříd. Označuje skutečnost, kdy třída je chápána jako vnějšími vlastnostmi popsaný objekt a není dále vysvětlena jeho vnitřní funkce.

Členská funkce je taková, která patří k jedné třídě. Zahrnuje chování objektů této třídy. Někdy se mluví o metodě.

Funkce je část kódu, která definuje odezvu programu na určitou událost. Funkce je posloupnost příkazů, které jsou při jejím volání postupně vykonávány.

str. 4

Page 5: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Třída jako datový typ je reprezentace skupiny objektů z řešeného problému se společnými vlastnostmi a způsobem chování.

Objekt je označení jak reálných typů, tak i objektových typů (instancí). Označení objekt se používá i pro oblast paměti, se kterou lze manipulovat (proměnná, konstanta, funkce, atd.)

Dědění je označení vztahů v hierarchii objektů a tříd. Třídy lze uspořádat do hierarchie a předávat (přebírat)-dědit tak vlastnosti (základních, rodičovských) tříd. Odvozená třída přebírá jak datové složky, tak metody. Odvozená třída představuje specializovanější objekt. Základní vlastností objektově orientovaného programování (OOP) je možnost zastoupení předka dědicem.

Událost popisuje přesně definovanou situaci nebo akci, na níž má program reagovat. Událostí je kliknutí na tlačítko v okně (OnClick), událostí je stisknutí klávesy na klávesnici (onKeyDown) či otočení kolečkem mezi tlačítky myši (OnMouseWheel). Pracujeme-li v Borland C++ Builder, píšeme tzv. událostmi řízený program. Pro události, na které má náš program reagovat, sestavujeme obslužné funkce. Vznik události odpovídající funkci automaticky vyvolá.

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

Objektově orientovaný je nazýván přístup, kdy problémy jsou řešeny jako zavádění, určování a implementace objektů ve formě tříd a práce s nimi. Jádro práce programátora spočívá v implementaci tříd do řešení problému a volání metod z implementovaných tříd. Knihovny tříd se dají opakovaně používat, tím se práce poněkud zjednoduší a OOP se přiblíží k lidskému způsobu uvažování.

Polymorfismus (mnohotvarost) je vlastnost, která umožňuje, aby jediný název byl použit jak pro více souvisejících a technicky odlišných účelů, tak pro rozdílné metody. Uvnitř třídy procesů je volba procesu dána typem dat.

Předefinování je proces, kdy se mění vlastnosti zděděné funkce v odvozené třídě. Důvodem je úprava funkce tak, aby reagovala správně na požadované volání. Předefinování je základním klíčem a krokem k realizaci polymorfismu.

Přetěžování funkcí je pojem, kdy několik funkcí má stejné jméno. Překladač potom rozlišuje podle počtu a složení a typů parametrů. Někdy se tento termín používá v souvislosti s hierarchií tříd a polymorfismem. Zde je ale namístě přesnější mluvíme-li o předefinování.

Přetěžování operátorů je schopnost rozšířit operátory o uživatelem definované typy. Překladač určuje, kterou operaci chceme provést.

Zapouzdření je mechanismus, kdy objekty v programu lze popsat svými vlastnostmi (data) a chováním (metoda), je spojen dohromady kód a data v jednom objektu. To lze shrnout do třídy, která objekt reprezentuje. Tím se přistupuje k objektu z vnějšku jako k souhrnu vlastností a reakcí.

Rozhraní je prostředek pro výměnu informací mezi funkcemi, třídami, moduly, atd. Rozhraní funkce je určeno jejími parametry, rozhraní třídy datové složky nebo členské funkce.

Skrývání informací a implementace je tendence vývoje překladače, taková, aby programátor o funkci nemusel vědět příliš mnoho informací, ale mohl ji používat.

V textu budeme střídat různá písma:

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

str. 5

Page 6: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Courier – části zdrojových textů Courier – klíčová slova ve zdrojovém textu Arial – název diskového souboru nebo adresáře Arial – nově zaváděný termín

1.2 Vlastnosti C/C++

V dnešní době je jazyk C a C++ považován za jeden ze základních programovacích jazyků. Jazyk umožňuje velmi rychle sestavit program, aplikaci pro graficky orientovaný systém, dokáže pracovat s daty, přistupovat k hardweru. Generuje velmi rychlý kompaktní kód a ten zůstává přenositelný mezi velkou skupinou počítačů. Jazyk má vlastnosti vyššího programovacího jazyka.

Při vyvíjení C++ byla zachována kompatibilita s jazykem C, nikoliv striktně. V jazyce C++ jsou některé konstrukce nepřípustné i když v jazyce C jsou běžné. Také se vyskytují shodné tvary konstrukce v obou jazycích, ale jsou jinak interpretovány. Základním rysem a krokem od C k C++ bylo zavedení tříd. Tím se otevřela cesta do objektového světa programování. Úspěch zavedení a používání obou jazyků spočíval v tom, že přechod od C k C++ byl snadnější díky téměř úplné kompatibilitě obou variant jazyka. Další výhodou C++ je jeho použití bez nutného využívání objektově orientovaného programování. Několik slov o koncepci jazyka C.

Jazyk C byl navržen pro systémové programování v UNIXu, byl pomocný prostředek pro velmi rychlé a snadné sestavení spustitelného kódu. Jeho rysy lze bodově označit

• Malé bohatství prvků • Velká rychlost programů • Připravenost pro modulární programování • Dobrá přenositelnost • Blízkost k operačnímu systému

Jazyk C++ postupem času reagoval na změny v hodnotách ve světě programování. Strojový čas je levnější, práce a čas programátora dražší. Charakteristika jazyka C++ je vyjádřena v několika bodech

• Jednoduchý a spolehlivý • Vysoký stupeň opakovaného použití (modulární stavba) • Snadná údržba • Srozumitelný (až intuitivně)

Požadavek srozumitelnosti a přenositelnosti vedl ke vzniku rozsáhlého množství knihovních funkcí, čímž se přenositelnost zhoršila. Různí výrobci překladačů přidávali různá vylepšení, čímž se vytvořila paleta modifikací jazyka. Tyto problémy bylo nutné vyřešit a vytvořit závazný standard. Problém řešila komise založená v roce 1983 Americkým národním institutem pro standardizaci (American National Standard Institute - ANSI). V roce 1989 přijala komise koncept jazyka ANSI a po té také organizace ISO (International Standards Organization).

Nabízí se otázka, co je to objektově orientované programování? Odpověď není snadná. Je to především způsob myšlení, uvažování a organizace vztahů objektů. Pokusíme se tento

str. 6

Page 7: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

pojem rozvést. Programování lze chápat jako organizování závislostí, vztahů a výkonných operací s předpokladem, že budou provedeny za předem dohodnutých podmínek (syntaxe jazyka, algoritmus programovaného problému, … ). První programy byly tvořeny nastavením přepínačů, později pomocí děrných štítků, pásek -jazyka symbolických instrukcí. Po roce 1955 se vývoj zaměřil na první překladače jazyka. Začaly se ale vyvíjet lineární dlouhé programy s často se opakujícími algoritmy. A tak se začalo programování vyvíjet směrem ke strukturovanému programování – definované struktury, podprogramy s rekurzivním voláním. Díky svým omezením v rozsahu bylo nutné vyvinout kvalitativně lepší přístup než je strukturované programování. A bylo na světě objektově orientované programování (OOP). OOP se inspirovalo dobrými znaky strukturovaného programování a doplnilo je novými koncepty. Základním znakem OOP je rozložení problému na základní prvky (komponenty) a ta je používaná jako samostatný a nezávislý objekt. Obsahuje své vlastní instrukce a data používané uvnitř objektu. Tím se sníží komplikovanost celkového programu a je možné vytvořit rozsáhlejší algoritmus. Charakteristickými vlastnostmi OOP je

• Zapouzdření (encapsulation)

• Polymorfismus-mnohotvarost (polymorphism) • Dědičnost (inheritance).

Zapouzdření je způsob chování objektu, kdy jsou kód i data objektu chráněny před zásahem z venčí. Při spojení kódu a dat vzniká objekt. Uvnitř objektu jak kód, tak data, funkce mohou být neveřejná (private) nebo veřejná (public). Neveřejná data jsou dostupná jen v daném objektu nebo jeho části. Pro uživatele se objekt jeví jako proměnná. Pokaždé, když si definujeme nový typ objektu, vytváří se nový typ dat. Uveďme příklad na deklaraci třídy. class BasicClass { // neveřejné vzhledem k BasicClass int a; public: // veřejné vzhledem k BasicClass double add(double x, double y; };

nebo jiná třída class camera { // znaky popsane hodnotami char *vyrobce, *typ; int PocetObjektivu, PocetOptickychElementu; Boolean digital, zrcadlovka, profi; public: // zpusob chovani void zapnout(); void manual(); void program(); void snimek(); void vyvolani();

str. 7

Page 8: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

void prohlizeni(); void vypnout(); };

Polymorfismus je vlastnost jazyka, překladače, kdy mohou být použity stejné názvy pro různě účely (objekty, funkce,…). Tam, kde polymorfismus nebyl zaveden, hrozilo nebezpečí shody názvů interních i uživatelských a následná kolize programu. Polymorfismus dovoluje vytvářet standardní rozhraní k příslušným procesům. Někdy se polymorfismem označuje přetěžování funkcí a operátorů. Původní význam byl zaveden pro virtuální funkce. Ukážeme si jednoduchý příklad na deklaraci třídy:

class TrA { public: void Fce(int); }; class TrB { public: void Fce(char*); }; void main() { TrA prvni; TrB druha; prvni.Fce(3); druha.Fce("pokus"); }

Dědičnost je proces, kdy jeden objekt může získat vlastnosti jiného procesu. Přesněji řečeno, může zdědit původní vlastnosti a doplnit je o vlastní, charakteristické pouze pro něj. Tato vlastnost OOP podporuje hierarchické uspořádání programu na místo plošného nebo lineárního uspořádání. Tím se zkracuje kód a zpřehledňuje.

1.3 Zásady, směrnice ANSI

Příčinou úspěšného zavedení jazyka C a C++ do počítačového světa bylo vytvoření a respektování několika zásad komisí ANSI. Zásady lze shrnout do následujících bodů:

• Důležitý je existující kód, ne existující implementace (v překladači). Kód by měl být zachován za cenu změny implementace překladače.

• Kód napsaný v jazyce C je přenositelný. ANSI kód nabízí programátorům možnost přenositelnosti programu v jazyce C ANSI mezi různými operačními systémy.

• Kód napsaný v C může být nepřenositelný. Existuje možnost vytvořit programový kód, který je vázán na určitý hardware a tím není přenositelný na ostatní.

str. 8

Page 9: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

• Ohlašovat odlišnosti od standardu. Neměla by nastat varianta, kdy překlad jednoho textu programu bude na různých překladačích interpretován různě. Pokud ano, musí být na tyto odlišnosti od ANSI programátor upozorněn.

• Standard je dohodou mezi implementátorem a programátorem. Zásada by měla vést k respektování jak výrobce překladače, tak programátora.

Nyní, když máme definovány základní pojmy a stanovena základní pravidla, budeme se věnovat procvičování jednotlivých částí. Dále si uvedeme některé příklady základních rozdílů mezi C, C++ a nové směry v C++.

1.4 Objektově orientované programování

Objektově orientované programování se nesestává pouze z rozšíření znalostí C na některé nové prvky C++. (použití namísto printf() nového cout<<). OOP začíná tam, kde se definuje třída, kde se používá zapouzdření, polymorfismus, kde vznikají knihovny tříd. Cesta k tomuto způsobu programování je v

• opakovaném používání stejných kódů • sestavení datových typů s použitím dědičnosti a polymorfismu • používání zapouzdření.

Kde jsou tato kritéria nepodstatná, je možné používat program napsaný v jazyce C.

1.5 Program- operační systém

Při psaní programu je dobré mít povědomí o hrubém rozdělení prvků v ovládaném zařízení (počítač,...). Jsou zde prvky, které vědomě ovládáme programem a prvky, které jsou ovládány „systémem“ bez našeho velkého přičinění. Například alokace paměti, adresace, uvolňování, ... se nás příliš nedotkne, my pouze požadujeme

int a=5;

a tím je pro nás nachystán prostor v příslušné části RAM a je podle syntaxe k dispozici. Schéma základních částí počítače je na obr.1.

Obr. 1 Událostmi řízený OS – osobní počítač

Operační systém

Zobrazovací jednotka - display

Vstupní jednotka- klávesnice

RAM Programy

Procesor

Sběrnice

Smyčka „server“

SW

Systémová fronta

HW

Fronta aplikací

str. 9

Page 10: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

1.6 Sestavení programu

Program lze v současných překladačích sestavovat pomocí generátorů, které přednastaví v textu umístění našeho programu, který reaguje na prvky graficky orientovaných aplikací. Rád bych velmi stručně naznačil organizaci a možnosti korektního vstupu do tohoto systému s vlastním programem, funkcí. Na obr.2 je schéma konstrukce klasických překladačů, pro DOS , MS Windows 1.0-95. V levé části je klasický způsob sestavení programu pro konzolový typ systému. K tomu se v 80-tých letech přidal systém s objekty a událostmi řízené programování. První prostředky používaly klasické konstrukce programu, jen přidávaly nové prvky. Bylo velmi snadné připojit pomocí souborů *.OBJ jakýkoliv externí program. Programování pro událostmi řízený chod se vyvíjelo a základní jádro organizace je na obr.3.

DOS MS Windows 1.0, 2.0, 3.0, 3.1, 95 Obr.2 Schéma sestavení programů pro platformy

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

str. 10

Page 11: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Pro korektní vložení vlastního zdrojového programu do existující šablony existuje několik přístupů. Pokusím se vybrané postupy vysvětlit. První, známý z kurzu Počítače a programování 2 je vložení textu přímo do vygenerované „šablony“. Tak se text přeloží a je spustitelný. Tato metoda je poněkud nepružná a „nemotorná“. Musíme mít editor textu, správný formát atd. #pragma hdrstop #include "Unit1.h" //------------------------------------------------------------------ #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)

----------------------------------------------------------

{} int void mojeExtFunkce( ) {/* text vlozene funkce*/} //-- ----------void __fastcall TForm1::fPokus(TObject *Sender)

- -----------------------------------------------------

{} //------------------------------------------------------------------ Účelnější a možná ne tak „obrázkově “ podporované je řešení, kdy do textu vložíme naši funkci pomocí hlavičkového souboru. Pokud funkce neobsahuje složité vazby na API a objekty uživatelského rozhraní, je to velmi rychlý způsob. Nepotřebuji k napsání programu žádný složitý prostředek, snad tužku papír a dostupný textový editor na použitém počítači. Text by vypadal si takto: #pragma hdrstop #include "Unit1.h" #include "mojeExtFunkce.h" //------------------------------------------------------------------ #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)

----------------------------------------------------------

{} //------------------------------------------------------------------ void __fastcall TForm1::fPokus(TObject *Sender) {} //------------------------------------------------------------------ Soubor mojeExtFunkce.h v adresáři, kde jsou umístěny soubory projektu má tento obsah int void mojeExtFunkce( ) {/* text vlozene funkce*/} Ještě snad chybí uvést schéma sestavování programu v současných překladačích. Na obr.4 je velmi zjednodušeně naznačeno. Některé typy souborů nemusí být použity, tvůrci překladačů

str. 11

Page 12: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

vytvářejí jiné soubory, dočasné soubory jsou mazány. Ale v zásadě je postup překladu zachován, směřuje od horních řádků k dolním.

*.h *.c *.h Soubory na disku Uživatelské soubory Systémové soubory

*.i

*.obj *.obj *.lib

*.dll

*.obj *.dll

*.lib

*.exe*.com

*.exe

Sestavení

DDE

Předzpracování, kontrola chyb

Překlad, kontrola chyb

Obr.4 Postup sestavení spustitelného souboru

1.7 Základní prvky zápisu blokového schématu

Abychom mohli srozumitelně zapisovat algoritmy programů, seznámíme se se základ-ními značkami, které se objevují v blokových schématech.

Značka pro předepsaný postup:

A=B, A=A+1, A=A*B

Značka pro načtení, výstup

Vstup A, Výstup A

Značka pro rozhodnutí

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

Značka pro začátek, konec

začátek konec

Značka pro funkci, podprogram

str. 12

Page 13: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Značka pro cyklus

cyklus I = 1, .., N

Značka pro skok

skok na

1.8 Algoritmy

Má-li se řešit nějaká programátorská úloha, naskytne se více přístupů a postupů řešení. Z nich je třeba vybrat jeden postup a ten formulovat pomocí vývojového diagramu. Pro výběr se musí určit nějaká kritéria, podle kterých se zvolí postup řešení programu. Musí se tedy roz-hodnout, který postup je „lepší“ a který je „horší“. Co to je „lepší“ a „horší“? Kritéria pro po-suzování kvality algoritmu jsou jak subjektivní tak objektivní. Dále se budeme zabývat více těmi objektivními kritérii. Základní objektivní kritéria hodnocení algoritmu tedy jsou:

1. Rychlost algoritmu (výpočtu) 2. Paměťová náročnost – operační i externí paměť 3. Stabilita algoritmu

Problematika těchto kritérií je velmi rozsáhlá, ale pro účely tohoto textu se budeme držet nut-ných pojmů a praktických důsledků bez uvedení odvození a důkazů.

Prvně dvě kritéria jsou významná hlediska při hodnocení algoritmů. Jsou odlišná a velmi často stojí proti sobě. Bývají algoritmy takové, že jeden z nich je pomalejší, ale po-užívá malou operační paměť, zatímco druhý je rychlejší, ale má vysoké nároky na operační paměť. To je často způsobeno tím, že pro zrychlení algoritmu je použita další pomocná pro-měnná nebo množina proměnných, které budou uchovány v operační paměti. Tím se zvětší nároky na paměť za cenu zrychlení výpočtu. Pro volbu paměťové náročnosti a rychlosti ne-existuje obecné řešení, záleží vždy na požadavcích, které jsou kladeny na program. Samozřej-mě první dvě kritéria jsou závislá také na použitém technickém vybavení (hardware). Jako příklad lze uvést úlohu vyhledání telefonního čísla v seznamu. Jedním z postupů je vyhledání čísla tak, že začneme procházet seznam od počátku, až nalezneme to hledané. Tento postup se nazývá sekvenčním vyhledáváním. Ve skutečnosti jsou jména v seznamu seřazena podle abecedy. Postup při vyhledávání je podle srovnání rostoucích n-tic písmen jména. Pokud hledané jméno je Novák, první n-tice je N. Dále je hledána druhá n-tice No, atd.

Stabilita algoritmu závisí jak na vstupních údajích programu, tak na zvolené metodě algoritmu. Doba výpočtu i paměťové nároky bývají také závislé na vstupních údajích. Pro-gram většinou řeší celou třídu podobných problémů, které se liší právě zadávanými vstupními údaji. Ale trvání výpočtu i paměťové nároky často neovlivňují konkrétní zadané hodnoty, jen velikost vstupních dat. Prakticky, je jedno zda vyhledávám jedno telefonní číslo v telefonním seznamu s 3000 položkami nebo vyhledávám naměřenou teplotu s 3000 údaji. Ale je rozdíl, pokud vyhledávám telefonní číslo v seznamu Znojma a Brna. Potom bude algoritmus mít rozdílnou dobu trvání.

str. 13

Page 14: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Paměťová náročnost u algoritmů se uvádí v jednotkách jakými jsou bit nebo bajt. Bit je jednotka, která může být nuď ve stavu logické jednotky nebo ve stavu logické nuly. Bajt je jednotka (slovo), která je složena z několika bitů. Počet bitů v bajtu je dán mnoha kritérii. Jsou obvykle používány 8, 16, (24), 32, 64, 128, … bitová slova.

Časová náročnost se udává v souvislosti s použitým typem procesoru, velikostí RAM a její rychlosti, konfiguraci základní desky, typem a výrobcem operačního systému. Udává se buď jako doba pro nejhorší případ složitosti algoritmu se vstupními daty velikosti N nebo jako průměrný případ výpočtu z N vstupních dat.

Algoritmy se porovnávají v jejich časové náročnosti. Ta je porovnána a je rozhodnuto, který z nich je rychlejší. Stává se, že vstupní data a jejich rozsah nejsou specifikovány. Potom nelze stanovit časovou náročnost. Postupuje se tak, že se zvolí pro rozsah dat velké číslo N a provede se srovnání algoritmů s uvedením podmínek. Jedná se tedy o asymptotickou časo-vou náročnost. Tedy časová náročnost lepšího algoritmu roste pomaleji s rostoucími hodno-tami N. Časovou náročnost lze popsat typem funkce a jejím řádem. Rozeznáváme tedy zá-kladní polynomiální a exponenciální funkce. Následuje ukázka zadání a vypracování algoritmů základních až triviálních úloh.

Příklad 1. Sestavte a nakreslete diagram algoritmu pro nalezení minimálního čísla z řady N zadaných. Nechť je výsledek zobrazen na výstupním zařízení.

Začátek

čti N

A=1e99

I=1,..,N

čti číslo X

X<A + -

A=X

vypiš MinimumA

Konec

Příklad 2. Sestavte a nakreslete diagram algoritmu pro nalezení maximálního čísla

z řady N zadaných. Nechť je výsledek zobrazen na výstupním zařízení.

str. 14

Page 15: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Začátek

čti N

A=1e99

I=1,..,N

čti číslo X

X<A + -

A=X

vypiš MinimumA

Konec

Příklad 3. Sestavte a nakreslete diagram algoritmu pro nalezení součtu čísel z množiny

A 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 je M. Nechť je výsledek zobrazen na výstupním zařízení.

Začátek

čti N, M

celá A(N), celá B(M) A(1)= .., A(N)=… B(1)= .., B(M)=… SOUCET=0

I=1,..,N

B(J) ≠0 + -

SOUCET= SOUCET+B(J)

vypiš Součet prvků množinyA a B, SOUCET

Konec

J=1,..,M

A(I)≠0 + -

SOUCET= SOUCET+A(I)

Příklad 4. Sestavte a nakreslete diagram algoritmu pro nalezení součinu čísel z množiny A 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 je M. Platí, že M=N. Nechť je výsledek zobrazen na výstupním zařízení.

str. 15

Page 16: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Začátek

čti N, M

reálná A(N), reálná B(M) A(1)= .., A(N)=… B(1)= .., B(M)=… SOUCIN=1

B(J) ≠0 ∧ A(J) ≠0

+ -

SOUCIN= SOUCIN+A(J)*B(J)

vypiš Součin prvků množinyA a B, SOUCIN

J=1,..,M

M≠N +

Konec

-

SOUCIN A a B je roven 0

Příklad 5. Sestavte a nakreslete diagram algoritmu pro porovnání obsahu množiny A

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 je M. Pokud množiny mají společný prvek (číslo) zobrazte je na výstupním zařízení.

Začátek

čti N, M

celá A(N), celá B(M), celá C(X) A(1)= .., A(N)=…B(1)= .., B(M)=… Spolecna=0, K=0

I=1,..,N

B(J)=A(I) + -

C(K)= A(I)

Počet společných prvků KSpolečné prvky C(1,..,K)

Konec

J=1,..,M

M>N +

X=M - X=N

K=K+1 Spolecna=1

Spolecna = 0+

-

Příklad 6. Sestavte a nakreslete diagram algoritmu pro průnik C obsahu množiny A 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 je M. Množinu C zobrazte na výstupním zařízení.

str. 16

Page 17: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Začátek

čti N, M

reálná A(N), reálná B(M), reálná C(X) A(1)= .., A(N)=…B(1)= .., B(M)=… Prunik=0, K=0

I=1,..,N

B(J)=A(I) + -

C(K)= A(I)

Počet společných prvků KC(1,..,K)

Konec

J=1,..,M

M>N +

X=M - X=N

K=K+1 Prunik=1

Prunik = 0 +

-

Příklad 7. Sestavte a nakreslete diagram algoritmu pro sjednocení C obsahu množiny A 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 je M. Množinu C zobrazte na výstupním zařízení.

Začátek

čti N, M

reálná A(N), reálná B(M), reálná C(M+N) A(1)= .., A(N)=…B(1)= .., B(M)=… Reálná Pomocna=0, celá L=0

I=1,..,N

B(J)≠A(I) + -

Pomocna= A(I)

Počet prvků L C(1,..,L)

Konec

J=1,..,M

K=1,..,M+N

C(K)=Pomocna + -

L=L+1 C(L)=Pomocna

Příklad 8. Sestavte a nakreslete diagram algoritmu pro zjištění, zda zadané číslo N je prvočíslo.

str. 17

Page 18: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Začátek

čti N

I=2,..,celé(√N)

+ -

N je prvočíslo

Konec

A=B

Prvocislo= 1

A=celé(N/I)

reálné A, reálné B

B=N/I

Prvocislo= 0

Prvocislo=1 +

-

N není prvočíslo

Začátek

čti N, M

reálná A(N), reálná B(M), reálná C(M+N) A(1)= .., A(N)=…B(1)= .., B(M)=… Reálná Pomocna=0, celá L=0

I=1,..,N

B(J)≠A(I) + -

Pomocna= A(I)

Počet prvků L C(1,..,L)

Konec

J=1,..,M

K=1,..,M+N

C(K)=Pomocna + -

L=L+1 C(L)=Pomocna

Příklad 9.Sestavte a nakreslete diagram algoritmu pro výpočet funkce 5555.

Začátek

reálná A(40), reálná D A(1)=1.0

I=1,..,555

Konec

J=1,..,39

D=0.0

A(J)= 5*A(J)+D D=celé číslo (A(J)/1010 ) A(J)=A(J)-D*1010

I=39,..,1

Výpis A(I)

Příklad 10. Sestavte a nakreslete diagram algoritmu pro součet matic A a B. Prvky množiny A i 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 na výstupním zařízení.

str. 18

Page 19: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Začátek

čti N, M

reálná A(M,N), reálná B(M,N), reálná C(M,N) A(1,1)= .., A(1,N)=…B(1,1)= .., B(1,N)=… C(1,..,M,1,..,N)=0.0

I=1,..,N

Výstup matice C(M,M)

Konec

J=1,..,M

C(I,J)= C(I,J)+A(I,J)+B(I,J)

Příklad 11. Sestavte a nakreslete diagram algoritmu pro součin matice A a vektoru B.

Prvky 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 zobrazte na výstupním zařízení.

Začátek

čti N, M

reálná A(M,N), reálná B(N), reálná C(N) A(1,1)= .., A(1,N)=…B(1)= .., B(M)=… C(1,..,N)=0.0

J=1,..,N

Výstup sloupcové matice C(M)

Konec

I=1,..,M

C(J)= C(J)+A(I,J)*B(I)

Příklad 12. Sestavte a nakreslete diagram algoritmu pro součin matic A a B. Prvky

množiny A i B jsou reálná čísla, počet prvků množiny A je N×N a množiny B je M×M. Množi-nu C zobrazte na výstupním zařízení.

str. 19

Page 20: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Začátek

čti N, M

reálná A(M,N), reálná B(N,M), reálná C(N,N) A(1,1)= .., A(M,N)=…B(1,1)= .., B(N,M)=… C(1,..,N, 1,..,N)=0.0

I=1,..,N

Výstup matice C(N,N)

Konec

J=1,..,M

C(I,K)= C(I,K)+A(J,I)*B(K,J)

K=1,..,N

1.9 Kontrolní otázky

1. Vysvětlete, co je to abstrakce a jak se využívá?

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

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

4. Jak byste charakterizovali vlastnosti jazyka C++?

5. Jaké jsou základní vlastnosti a rysy objektově orientovaného programování?

6. Pro uvedené příklady algoritmů napište v C++ jednoduché funkce.

1.10 Úkoly

1. Sestavte jednoduchou funkci, odlaďte ji a spojte s jednoduchým programem v Borland Builderu.

2 Některé rozdíly C a C++

Mezi jazyky C a C++ i přes jejich podobnost existují drobné rozdíly. Předpokládejme, že čitatel má základní znalosti z programování v C a orientuje se v problematice. Pokusím se pomocí tabulky ukázat některé rozdíly v obou jazycích.

str. 20

Page 21: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

OBSAH C C++ VÝZNAM

prototyp funkce Fce() int Fce (void)

prototyp funkce Fce() int Fce (),

int Fce(void)

prototyp funkce nepovinný povinný

deklarace funkce s návratem hodnoty

nemusí vracet (nebo vrací int)

musí vrátit vždy

deklarace lokálních proměnných

začátek bloku před výkonnými proměnnými

kdekoliv

typ proměnné bool, klíčová slova true, false

Zde ještě pro doplnění a upřesnění doplníme některé často používané pojmy, které se mohou nesprávně interpretovat. Mezi první dva patří deklarace a definice. Deklarace seznamuje počítač s názvem proměnné, funkce, třídy šablony nebo datového typu.

• Deklarací stanovíme její typ, paměťovou třídu a viditelnost jejího identifikátoru. Stanovíme také typ vracené hodnoty a počet, pořadí a typy parametrů a eventuálně jejich implicitní hodnoty.

• Deklarace v C++ začíná klíčovým slovem extern.a neobsahuje inicializaci • Popis statické datové složky v deklaraci třídy je jen deklarace, nikoliv definice • Mezi deklarace patří typedef, using.

Definice nejen popisuje objekt, ale přikazuje překladači, aby ji zřídil.Proměnné, funkce a další součásti programu dostupné v celém těle programu mohou mít více deklarací. Statické proměnné a funkce mohou mít v kterémkoliv z modulů jinou definici.

• Definice proměnné v C++ buď neobsahuje klíčové slovo extern nebo obsahuje inicializaci.

• Definice funkce obsahuje její tělo • Statické datové složky tříd musíme definovat někde za deklarací třídy (mimo tělo

funkce) Z kurzů Počítače a programování 1 a Počítače a programování 2 jsou známy základní informace o datových typech, výčtových typech, polích jedno a vícerozměrných, řetězcích, strukturách, bitových polích, uniích, ukazatelích, dynamických proměnných, práci s ukazateli. Pokračovali bychom dále v prohloubení znalostí z oblasti tříd.

2.1 Klíčová slova C++

NÁZEV VÝZNAM POZNÁMKA

asm auto

str. 21

Page 22: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

bool break case catch char class const const_cast continue default delete do double dynamic_cast else enum explicit extern false float for friend goto if inline int long mutable namespace new operator private protected public register reinterpret_cast return short signed sizeof static satic_cast struct switch teplate this throw true

str. 22

Page 23: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

try typedef typeid typename union unsigne using virtual void volatile wchar_t while

2.2 Úkoly

1. Sestavte jednoduchou funkci, vyzkoušejte změny mezi syntaxí C a C++, odlaďte ji a spojte s jednoduchým programem v Borland Builderu.

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

předepisovat různá oprávnění k přístupu k jednotlivým prvkům. Třídy mají díky dědičnosti hierarchické uspořádání. Deklarace může být zapsána:

klíč třída[:seznam_předků] { deklarace_prvků }[případ1,případ2,...];

kde jsou klíč .... class, struct nebo union. V C++ struktury a unie představují pouze zvláštní

případy tříd. třída ....identifikátor třídy, :seznam_předků....seznam identifikátorů tříd, jejichž vlastnosti má nová třída zdědit deklarace_prvků....v těle třídy se deklarují její složky. Přístup k prvkům mohou

upravovat specifikátory přístupových práv (public, protected, private). případ1....zde se mohou definovat případy (instance), ukazatele na případy, pole

případů. Uveďme si konkrétní příklad. class Priklad { int H

public: odnota; // private

druha(){protected:

Hodnota=1;}; //konstruktor

int treti(){ return Hodnota;};

str. 23

Page 24: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

private: int Posledni();

}; • Specifikace přístupových práv platí pro všechny složky, které jsou zapsány za ní, až

do další specifikace. • Specifikace přístupových práv se mohou v deklaraci třídy vyskytovat vícekrát. • Složky třídy na začátku deklarace před první specifikací přístupových práv jsou

automaticky považovány za o soukromé (private) ve třídách definovaných pomocí klíčového slova class. o veřejné (public) ve třídách definovaných jako struct a union.

Specifikace přístupových práv se nevztahují na spřátelené funkce. Používání tříd v OOP se řídí jistými pravidly. Rozlišují se vlastnosti a způsob chování objektů. Společné objekty lze zahrnout do jedné třídy. Například: class Mesto { /* znaky popsane hodnotami*/ char *Nazev; int PocetObyvatel; boolean MestskaDoprava, Silnice, Dalnice, Metro, Letiste, Divadlo, park, Obchod, Skola; public: /*zpvoid Ubytovani();

usob chovani*/

void Zamestnani(); void Odpocinek(); void Sport(); void Doprava(); }; Pokud podle dané třídy deklarujeme proměnnou – případ (instance), musí být datovým složkám přidělena hodnota. Potom deklarovaná proměnná představuje jediné identické město- např. Brno. Mluvili jsme o zapouzdření dat a členských funkcí . Pro práci s třídami se může ještě přidat další pojem- skrývání dat. Je to stav, kdy programátor používá členské funkce třídy a nestará se jak program vykoná na připojeném HW zamýšlené operace. Například v třídě Mesto pro případ Brno bychom spustili funkci Brno.Doprava(); a tím by program podle těla funkce řídil dopravu v celém městě Brně. Programátora ale již nezatěžuje, jak se přes rozhraní počítače provádí spouštění systémů pro řízení křižovatek, tram. a autobusové dopravy. Dalším pojmem je uzavřenost. Tím se myslí takové nadefinování třídy, které je úplné (neobsahuje zbytečně mnoho nebo málo údajů) a je právě vhodná k provádění operací podle jejího chování.

3.1 Datové složky

Třídy mají datové složky. Každý případ dostane k dispozici paměť pro datové složky. Při jejich tvorbě dojde k jejich inicializaci- přiřazením hodnot. Toto přiřazení provede konstruktor. Datové složky zanikají se zánikem proměnné. Operaci má na starosti destruktor.

Datové složky mohou být deklarovány jako:

str. 24

Page 25: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

• veřejně přístupné (public) • chráněné (protected) • soukromé (private) • Mohou být deklarovány jako statické (static). • Statické složky jsou společné pro všechny případy (instance). Vznikají při spuštění

programu- jedná se o globální proměnnou, zapsanou ve třídě. • Statické složky nemohou být deklarovány jako auto, register, extern. • Zápis statické složky v definici třídy je jen deklarace. Definice se provede vně třídy. • Statické složky se mohou používat prostřednictvím jména třídy

(JmenoTridy::StatickyPrvek) • Statické složky nelze deklarovat pomocí const.

Složky, které jsou deklarovány jako const, musí se inicializovat, ale pak je dále nelze měnit (konstanty). Složky mohou být deklarovány jako mutable. Tyto složky jsou měnitelné i když je případ deklarován jako const. Složky mohou být deklarovány jako volatile, ta může neočekávané (asynchronně) měnit svůj obsah. Překladač neoptimalizuje (zkracuje, upravuje) operace s touto proměnnou. Třída nemůže obsahovat jako datovou složku sebe sama. Ale může obsahovat ukazatel nebo reference na nedefinovanou třídu (i na sebe sama). Příklad 1: class test { int PocetObyvatel; class priklad a; //chyba class priklad* b; //dobre class priklad &c; //dobre }; Lokální třídy Třídy, které jsou definovány v příkazové části funkce, se označují jako lokální. Jsou omezeny a všechny metody se musí definovat v těle třídy. Vnořené třídy Uvnitř třídy se může jako složka deklarovat datový typ. Tedy i třídu. Příklad 2: int i; class Vnejsi {

static int n; public:

int i; static float f; class vnitrni { void test(Vnejsi &glob) { i=5; // Ma byt glob.i

str. 25

Page 26: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

f=1; // Spravne ::i=1; // odkaz na globalni i glob.i=-1; // Spravne, i z tridy global n=5; // Chyba }; }; class priklad* b; //Dobre class priklad &c; //Dobre

};

3.2 Členské funkce- metody

• Mohou být deklarovány jako public, protected, private. • Pokud jsou definované jako static, pak pracují pouze s datovými složkami static. • Metody mohou pracovat s objekty typu const. Metody mohou být deklarovány jako

virtual, inline. • Mohou být přetěžovány pouze členskými funkcemi stejné třídy. • Mají přístup ke všem prvkům své třídy bez ohledu na přístupová práva. • Jsou jediným prostředkem s funkcemi typu friend, jak získat přístup k soukromým

prvkům- private. • Metody mohou být deklarovány jak uvnitř, tak vně deklarace třídy.

Příklad 3: class test {

int n; public:

test() { n=1; } void test2() const {n=2;} // Chyba int test3() const {return n;} int test4(){return n;}

}; Definice metody uvnitř definice třídy Metody definované uvnitř definice třídy jsou překládány jako inline. Doporučuje se definovat uvnitř třídy pouze krátké přehledné funkce. Definice metody vně definice třídy U této definice se musí ke jménu metody připojit jméno třídy pomocí operátoru rozsahu.

str. 26

Page 27: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Příklad 4: class test {

int n; public:

test() { n=1; } int Test3Vrat() const {return n;} //definice int Test4Smaz() //definice

}; inline test::Test4Smaz() {n=0;} Přístup k prvkům tříd Velmi osvědčené je, jsou-li třídy navrženy tak, že prvky jsou typu private. Potom je mohou používat jenom metody dané třídy. Vně třídy k nim mají přístup pouze členské funkce. Přístup zevnitř třídy Příklad 5: class test { private:

int n1, n2; int fun1() {return n1*n2;};

public: void fun2(int j) { n1=j+1; n2=fun1(); }

}; test z; z.fun2(222); // Změna z.n1 a z.n2 Přístup z vnějšku třídy Pokud se pracuje a přistupuje z vnějšku třídy k prvkům třídy, musí se uvést případ, pro který chceme složky měnit. Přístup je pomocí případu a operátoru tečka- jméno složky nebo ukazatel a připojíme jméno složky pomocí operátoru -> .

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

str. 27

Page 28: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Příklad 6: class test { //První dvě jsou soukromé

int n1; int fun1();

public: int n2; int fun2();

}; void main() {

test z, *PokusD; int i; i=z.n1; // Nespravne i=PokusD->fun1(); // Nespravne i=z.n2; // Spravne i=

return 0; PokusD->fun2(); // Spravne

}

• Přístupem přes přátele se obejdou pravidla přístupu. Klíčové slovo je friend. Zápis je

friend ProtoypFunkce; friend class JmenoTridy; Aby se tyto přístupy podařilo provést, musí být funkci předán ukazatel na případ, reference na případ nebo přímo případ třídy. Příklad 7: class test {

int n1; friend void fun1(test&);

}; void fun1(test& objekt) { int a; a=objekt.n1; } void main() { class test T;

fun1(T); return 0; }

• Třída určuje, které funkce jsou spřátelené a chrání tak data před nekontrolovaným použitím.

• Jako spřátelené funkce mohou být deklarovány i metody jiných objektových typů. • Mimo deklarace spřátelených funkcí se může deklarovat celá třída jako spřátelená.

str. 28

Page 29: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Přetěžování a předefinování Pokud se v odvozené třídě deklaruje nevirtuální metoda se stejným jménem jako v bázové třídě, zastíní deklarace v odvozené třídě deklaraci z bázové třídy. To je stav, kdy zděděná metoda nebude přímo dostupná i když je odlišná. Pro její použití se musí použít jméno předka. Příklad 8: class Zaklad {

public: void fun1(int);

}; class Odvozena:Zakld {

public: void fun1(char*);

} ;

void main() { Odvozena odv;

odv.fun1(3); // chyba odv.Zakld::fun1(3); // spravne

return 0; } Zvláštní metody Mezi zvláštní metody patří vytvoření případu- konstruktor. Ten má několik pravidel použití. Základní jsou:

• Konstruktor má vždy stejné jméno jako jeho třída • Konstruktor nemá žádnou návratovou hodnotu • Pokud konstruktor nedeklarujeme, překladač v třídě sám vytvoří veřejně přístupný

konstruktor bez parametrů • Pokud explicitně deklarujeme jakýkoliv konstruktor, nebude překladač žádný další

vytvářet • Konstruktory mohou být přetěžovány • Konstruktory se nedědí, konstruktor potomka automaticky volá konstruktory

bezprostředních prvků • Nelze deklarovat ukazatel na konstruktor • Konstruktory, které mají právě jeden parametr, mohou provádět konverzi na typ své

třídy • Konstruktor se volá při dynamické alokaci případu pomocí operátoru new.

Příklad 9: class test { int privat;

public: test(int i){privat=1;} //Konstruktor

str. 29

Page 30: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

explicit test(float g){privat=(int)g;} } ;

void main() { test pripad(100); test pripad2=100; //Implicitni konverze test pripad3(3.2); test pripad4=3.2; //Chyba: explicitni konverze

// parametru neni return 0; } Inicializační část konstruktoru Inicializační část je určena k inicializaci datových složek třídy. Má tvar identifikátor_složky (hodnota) identifikátor_složky (SeznamParametruKonstruktoru) identifikátor_třídy (SeznamParametruKonstruktoru) Příklad 10: class test { int i;

public: test(int j):i(j){} //do i je uložena hodnota parametru

}; class testB { test T; int x;

public: testB(int y):x(y-1), a(10){fce1();}

}; Zrušení případu -destruktor Destruktory se volají automaticky při zániku případu (například delete- zrušení dynamické proměnná).

• Destruktor nemá žádnou návratovou hodnotu • Pokud v třídě nedeklarujeme explicitně destruktor, vytvoří si překladač veřejně

přístupný standardní destruktor • Destruktor se nedědí • Nelze definovat ukazatel na destruktor • Destruktor nemá žádné parametry • Destruktory mohou být i virtuální • Destruktory můžeme explicitně volat.

str. 30

Page 31: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

3.3 Ukazatel this

Každý případ má svou kopii nestatických datových složek třídy. Metody jsou v paměti uloženy jen jednou a používají je všechny případy třídy společně. Je-li v nestatické metodě odvolávka na nestatickou datovou složku jejím identifikátorem, je to odvolání na aktuální případ vytvořené třídy. Ukazatel na aktuální případ Na aktuální případ se můžeme odkázat pomocí klíčového slova this. Ukazatel this se předává jako skrytý parametr a tedy programátor jej nemusí deklarovat. Na jednoduchém příkladu je ukázáno použití ukazatele. Příklad 11: class complex { double e, Im; R

public: complex(double _Re, double _Im):Re(_Re), Im(_Im){} double Real(); double Imag();

}; double complex::Real(){return Re;} double complex::Imag(){return Im;}

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

3.4 Agregáty

Agregáty jsou třídy, struktury nebo unie, které nemají

• žádný explicitně definovaný konstruktor • nestatické prvky, deklarované jako private nebo protected • nestatické reference • nestatické konstatní složky (const) • bázové třídy • virtuální členské funkce.

Agregáty je možné inicializovat výčtem hodnot ve složených závorkách. Příklad 12: class test {

public: struct Struktura { int i; float p;

}Str;

str. 31

Page 32: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

void fun1(); }; test T = {3,3.1415926};

3.5 Oblasti platnosti a dosažitelnosti identifikátorů

Blok Identifikátor deklarovaný v těle funkce je platný v místě jeho deklarace a končí na konci

bloku. Formální parametr funkce je platný na začátku jeho deklarace a končí na konci těla

funkce.

Funkce Oblast platnosti se týká pouze návěští pro příkaz skoku.

Prototyp funkce Oblast platnosti končí s koncem prototypu.

Soubor Oblast platnosti se týká globálních identifikátorů (deklarované mimo tělo funkce). Platnost začíná v místě deklarace a končí na konci souboru.

Třída Oblast platnosti identifikátoru definovaného uvnitř třídy začíná v místě deklarace, obsahuje celé tělo třídy, těla všech metod, specifikace formálních parametrů a jejich implicitních hodnot a také inicializační část konstruktorů i mimo tělo třídy. Jména deklarovaná uvnitř třídy jsou dostupná i mimo třídu když jsou zapsány případem (operátor tečka), ukazatelem na případ (operátor ->), někdy jménem třídy (operátor ::).

3.6 Prostory jmen

Tyto prostory jsou nástroje vhodné pro organizaci identifikátorů v programu, aby nedošlo ke konfliktům identifikátorů v rozsáhlém programu. Deklarace prostoru jmen je

namespace [jmenovka]{deklarace}

• Pokud překladač najde druhý prostor jmen se stejnou jmenovkou, bude jej považovat za rozšíření prostoru.

Příklad 13: namespace test { int i=1; //test::i

void fun1(int); struct T { int i=2; //test::T::i };

str. 32

Page 33: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

} namespace test // pokracovani { int i=3; //nepripustne- opakovana definice

void fun1(float); // pretizeni void fun2(float); // korektni namespace // nepojmenovany prostor { int i=4; //test::T::i };

} void test::fun1(float x); // definice vne prosteru { return i; // test::i }

• Prostory jmen můžeme deklarovat pouze na úrovni souboru nebo uvnitř jiného prostoru jmen.

• Spřátelené funkce, které jsou deklarovány uvnitř třídy, která zase byla deklarována uvnitř prostoru jmen, patří do daného prostoru jmen.

• Pomocí klíčového slova using lze zpřístupnit objekt z libovolného prostoru jmen bez nutnosti opakované deklarace.

using jmenovka :: idetnifikátor using namespace jmenovka V prvním příkladu se zpřístupní uvedený identifikátor, v druhém všechny identifikátory z daného prostoru. Příklad 14: namespace A { int i=1; } namespace B { int i=2; using namespace A; } void main() { i=i+1; // Není zpřístupněn A::i=A::i+1; // korektní using namespace B; i=i+6; // Není jasné o který prostor jde A::i nebo B::i return 0; }

str. 33

Page 34: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

3.7 Paměťové třídy

Při deklaraci můžeme ještě zadat pro proměnnou její paměťovou třídu. Paměťová třída a místo deklarace určují viditelnost a dobu života proměnné.

auto register static extern mutable

Auto proměnné jsou lokální v bloku. Register proměnné jsou automatické proměnné, u kterých požadujeme umístění do registru procesoru. Static proměnná je globální a má omezenou viditelnost. Extern se přiřazuje proměnné nebo funkci z vnějšího přístupu. Mutable povoluje měnit konstantní objekty.

3.8 Kontrolní otázky

1. V čem spočívají výhody tříd?

2. Má nějakou roli v úspoře času a prostoru při programování v C++ hierarchické členění objektů?

3. Existuje nějaké rozdělení přístupu k prvkům třídy?

3.9 Úkoly

1. Sestavte program pro načtení a uložení dat na disk s daty z tabulky jednoduché aplikace. Využijte maximálně vlastností OOP.

2. Sestavte program pro zadání a řešení soustavy lineárních rovnic Gaussovou eliminační metodou. Využijte maximálně vlastností OOP.

4 Objekty

Toto označení je používáno jak v běžném životě, tak v programovacích jazycích. Tam se pro srozumitelnost a pochopení snaží tvůrci jazyka napodobit vlastnosti prvků a názvosloví běžnému každodennímu životu. Objektem je tedy nazýván jak obraz třídy, tak i její případ (instance). Někdy se používá název objekt i pro přístupnou část paměti (konstanta, proměnná, pole proměnných, funkce, ...)

str. 34

Page 35: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

4.1 Přiřazování objektů

Předpokládejme, že objekt je popsán třídou. Pokusme se provést jednoduchou operaci se dvěmi objekty. Pokusme se objekt O1 přiřadit objektu O2. Příklad 15: using namespace A; class test { int a,b;

public: void fun1(int int j){a=i;b=j} i,void show()(cout << a<< ’ ’<<b<< ”\n”;)

}; void main() { test O1,O2; O1.fun1(5,6); O2=O1; // Prirazeni O1.show(); O2return 0;

.show();

} Při přiřazení objektů jsou data obou totožná, ale objekty jsou oddělené.

4.2 Předávání objektů funkcím

Objekty mohou být jako argumenty předávány funkcím tak jak známe z jazyka C. Platí shodná pravidla předávání (deklarace parametrů funkce – typ třídy, objekt třídy je argument funkce) Příklad 16: using namespace A; class test { int a;

public: pri =i} int get_a()(return a;)

(int i){a

}; int kva_a(test x) { return x.get_a()* x.get_a(); } int main() {

str. 35

Page 36: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

test a(5),b(6); cout << kva_a(a)<< ”\n”; cout << kva_a(b)<< ”\n”; return 0; } Program vytvoří třídu test. V ní je proměnná a. Funkce kva_a() přebírá argument třídy test. Na výstupu programu je číslo 25 a 36. Toto předání bylo provedeno hodnotou. Existuje také možnost předání adresou.

4.3 Vrácení objektů funkcemi

Tak jak je možné předávat objekty funkcím, mohou funkce objekty vracet. Funkce musí být deklarovaná tak, aby mohla třídu vrátit- return. Při této operaci se dočasně vytvoří objekt, v němž je návratová hodnota. Objekt je vrácen a dočasný objekt je zrušen. Příklad 17: using namespace A; class test { char a[100];

public: void show(){cout << a << ”\n”;} void set_a(char *str)(strcpy(a,str);)

}; // navrat typu test test inp() { char a[100]; tets str; cout << “Vloz znak:”; cin >> a; str.set(a); return str; } int main() { test O1; O1=inp; O1.shoreturn 0;

w();

}

str. 36

Page 37: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

V programu funkce inp() vytváří lokální objekt str. Následuje načtení řetězce z klávesnice. Řetězec je nakopírován do str.a pak jej funkce vrací do str. Objekt je vrácen po volání inp() do O1 v hlavním programu.

4.4 Úkoly

1. Sestavte program pro načtení a uložení dat z tabulky. Provádějte základní operace

s prvky tabulky.

5 Operátory V této části se budeme blíže zabývat vlastnostmi operátorů.

5.1 Přehled operátorů

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

OPERÁTOR POPIS POZNÁMKA + součet operandů (binární) + identita (unární) - rozdíl operandů (binární) - změna znaménka (unární) += součet operandů a přiřazení výsledku

levému operandu

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

* aritmetické násobení * přístup k hodnotě proměnné (ukazatel) *= aritmetické násobení a přiřazení výsledku

levému operandu

/ aritmetický podíl dvou operandů /= aritmetický podíl dvou operandů výsledek je

přiřazen levému

% výsledek po celočíselném dělení %= výsledek po celočíselném dělení výsledek

přiřazen levému operandu

! logická negace not logická negace != logická relace nerovná se not_eq logická relace nerovná se & adresa operandu (unární) & konjunkce po bitech (binární) bitand konjunkce po bitech (binární)

str. 37

Page 38: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

&= konjunkce po bitech a výsledek přiřadí levému operandu

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

&& konjunkce- logický součin and konjunkce- logický součin (int).... přetypování na int, lze libovolně použít dynamic_cast přetypování v rámci dědické hierarchie

s dynamickou kontrolou typů

static_cast změna typů objektů a standardní C/C++ const_cast změna typů, kdy se předávají nebo

odstraňují modifikátory const a volatile

reinterpret_cast nepřenositelné přetypování , čárka, operátor pro sekvenční

vyhodnocování

++ zvýšení hodnoty operandu o jednu -- snížení hodnoty operandu o jednu -> přístup ke složce případu (instance)

prostřednictvím ukazatele

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

= přiřazení == logická relace rovno < logická relace menší než > logická relace větší než <= logická relace menší nebo rovno => logická relace větší nebo rovno << posunutí bitů doleva <<= posunutí bitů doleva a přiřazení výsledku

levému operandu

>> posunutí bitů doprava >>= posunutí bitů doprava a přiřazení výsledku

levému operandu

?: podmíněný výraz [] indexování pole () volání funkce ^ bitová nerovnost XOR xor bitová nerovnost XOR ^= bitová nerovnost a přiřazení výsledku

levému operandu

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

| logická relace disjunkce – OR po bitech bitor logická relace disjunkce – OR po bitech |= logická relace disjunkce po bitech a

přiřazení výsledku levému operandu

or_eq logická relace disjunkce po bitech a přiřazení výsledku levému operandu

|| logická relace disjunkce - OR

str. 38

Page 39: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

or logická relace disjunkce - OR ~ doplněk (binární) compl doplněk (binární) : inicializace třídy :: operátor rozsahu, zpřístupnění globálního

jména, jména ze tříd a prostorů jmen

.* přístup k hodnotě třídy s pomocí případu ->* přístup k hodnotě třídy s pomocí ukazatele

na případ

sizeof vrací velikost operandu v bytech typeid dynamické určení typu new dynamické přidělení paměti delete uvolnění dynamicky přidělené paměti delete[] uvolnění dynamicky přidělené paměti pole # převod parametru makra na řetězec

(preprocesor)

## spojování symbolů (preprocesor) defined test na přítomnost definovaného makra

(preprocesor)

Podle počtu operátorů můžeme operátory klasifikovat na

• unární • binární • ternární

Práce s operátory se řídí jistými pravidly. Pro jistotu a zvýšenou přenositelnost programu je vhodné používat k vymezení priority operátorů závorek. Operandy, které vstupují do relace, by měly být stejného typu. Pokud nejsou, bude provedeno jejich převedení (konverze). Tento převod má svá pravidla. Podle zkušeností ale nelze na ně spoléhat, mohou způsobit při přenosu zdrojového kódu a následného překladu nedozírné komplikace. Proto dobří programátoři řádně definují převody již při psaní zdrojového programu. Nebudeme se proto dále zabývat pravidly konverze. Na následujících příkladech zkusme ukázat některé použití operátorů.

5.2 Popis, užití operátorů

Unární operátory + , - mění hodnoty operandu. Pro binární operátory +, -, /, * , % platí

známá pravidla. Přiřazovací operátory jsou obdobně používány jako v jazyce C a ostatních jazycích. V jazyce C jsme se seznámili se složenými operátory.

Příklad 18: void main() { int a,b;

a=1; b=2; a+=b; // ekv. a=a+b return 0;

str. 39

Page 40: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

} Použití relačních a logických operátorů je standardní jako v jazyce C, podobně přístup k datům je shodný jako v jazyce C. Snad někdy mohou dělat obtíže přístupy k objektům. Pokusme se na jednoduchých příkladech ukázat použití možností přístupu. Příklad 19: struct test { char jmeno[100]; int cislo_vyr; }; void main() { test auto;

strcpy(auto.jmeno, ”Jaguar”); auto.creturn 0;

islo_vyr=51023659874515926;

} Příklad 20: struct test { char jmeno[100]; int cislo_vyr; }; void main() { struct test auto; struct test* p_auto=&auto;

strcpy(p_auto->jmeno, ”Jaguar”); p_auto->cislo_vyr=51023659874515926; return 0;

} Bitové operátory jsou definovány pouze pro celočíselné typy proměnných. V operandech se pracuje s jednotlivými bity. Patří sem operace AND, OR, NOT, COMPL.

Jako příklad práce s bitovými operátory lze uvést:

Příklad 20:

0110 0001 znak ´a´ &1101 1111 maska 0100 0001 znak ´A´

0100 0001 znak ´A´ |0010 0000 maska 0110 0001 znak ´a´

0001 1001

str. 40

Page 41: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

^0000 1100 0001 0101 Často nejsou používané nebo známé operátory new a delete. Slouží k přidělování a uvolňování dynamické paměti. Jsou náhradou dříve používaných funkcí ze skupiny malloc() a free(). Na několika příkladech si ukažme její použití. Příklad 21:

long double *x=new long double; //alokace neinicia- lizovane promenne

x=new long double (1,2); //alokace hodnotou 1,2

long double *xx=new long double*; //neinicial. promenna long double *x=new long double [5]; //alokace pole void (**fce_ptr)(int)); //deklarace ukazatele na

fci fce_ptr = new (void(*[3])(int)); //dekl. 3 ukaz. na fci class test { int i; public: test(); test(int); }*x_test; char te[sizeof(test)]; //deklarace tridy x_test=new test[10]; //alokace pole x_test=new(te) test; //konstrukce pripadu

tridy test * utest = new(nothrow) test(5); //nevyvolava vyjimky,

alokuje pripad tridy

Objekty vytvořené pomocí new mají neomezenou dobu trvání. Paměťová místa se musí uvolnit operátorem delete. Příklad 22:

class test *p =new test[10]; //alokace delete[] p; int **xx = new int*; delete x;

V následující části textu se velmi stručně dotkneme přetypování. Klasické přetypování z C je asi takovéto: Příklad 22:

int a; // double b,c; c=(double) a/b;

str. 41

Page 42: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Pokud se setkáme s komplikovanějším přetypováním, jakým je například přetypování ukazatele, je k tomu určen operátor dynamic_cast. Ukažme si na příkladu jeho použití. Příklad 23:

class zakl { public: virtual void fce(); }; // class dcera: public virtual zakl { public: virtual void fce(){} virtual void gfce(){int a=1;} }; // void pracuj(zakl *ub) { dcera* up = dynamic_cast<dcera*> (ub) if(up) up->gfce(); else return -1; }void main() { zakl X; dcera Y; pracuj (&Y); // pretypovani OK, ret.1 pracuj (&X); // pretypovani FALSE, ret. -1 }

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

Některé operátory (většina) v C++ lze předefinovat. Přetížené operátory se definují jako funkce (operátorové funkce). Při práci s operátory se mohou rozdělit do čtyř skupin:

1. Operátory ::, ?:, ., .*, sizeof, typeid, dynamic_cast, static_cast, reinterpret_cast, const_cast, defined, #, ## NELZE PŘETĚŽOVAT.

2. Operátory ->, [], (), =, (typ) lze přetěžovat pouze jako nestatické metody objektových typů.

3. Ostatní operátory s výjimkou new a delete lze přetěžovat jako nestatické metody objektových typů.

4. Operátory new a delete lze přetěžovat jako statické metody objektových typů nebo jako obyčejné funkce.

• Přetěžování operátorů má také svá pravidla. Například nelze definovat nové operátory. • Není přípustné měnit charakteristiky operátorů (počet operandů, prioritu,…) • Nelze měnit definici operátoru pro standardní datové typy. • Jméno operátorové funkce se vždy skládá z klíčového slova operator a symbolu

operátoru.

str. 42

Page 43: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

• Kromě new a delete operátoru není pro žádný z operátorů předepsán typ vrácené hodnoty.

Příklad 24:

class complex // komplexni cisla { double re,im; public: complex (double r, double i); // konstruktor x operator ; // unarni minus comple –() friend bool operator !(complex&); //logicka negace }; // complex complex::operator-() // vrati komplexni cisla

// s opacnym znamenkem { return complex (-re, -im); } complex operator!(complex& c) // pokud je aspon jedna slozka // nenulova, vrati true { if(c.re || c.im) return true; else return false; } void main() {

complex c(0,0), d(0,1); c=-d; // ekvivalent c=d.operator-() if(!c) test(c);

return 0; }

Takto bychom mohli pokračovat v dalších příkladech.

5.4 Úkoly

1. Sestavte program pro změnu editovaných písmen z malé na velkou abecedu a

obráceně.

str. 43

Page 44: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

6 Dědičnost Dědičnost je jedním ze základních vlastností a prvků OOP. Tím se dokáže rychleji

sestavit struktury vlastností objektů. Původní – bázové třídy slouží jako základ pro nové – odvozené třídy – potomky nebo dceřiné třídy. Třídy, které se vážou dědičnými vlastnostmi, se také označují jako dědické hierarchie.

Existuje několik forem dědičnosti. • Jednoduchá- jedna bázová a jedna odvozená • Vícenásobná – jeden potomek má více předků.

Odvozená třída dědí vlastnosti předků. Bude obsahovat všechny nestatické datové složky předků, bude používat jejich metody, typy a statické složky podle definovaných práv. Některá pravidla lze bodově shrnout:

• Kritérium sdílení- Odvozené třídy by měly korektně sdílet vlastnosti základní třídy. • Kritérium nezávislosti- Vlastní definice odvozené třídy by neměly ovlivňovat použití

zděděných vlastností. • Kritérium specializace- Je-li odvozená třída speciálním případem základní, použije se

k odvození polymorfismu – virtuálních metod. Speciální případy tříd nejsou rozdílné úrovně v hierarchii.

• Kritérium jednotnosti – dědičnost by měla zajistit rovnoprávnost tříd – jednotný způsob implementace.

Jak se s dědičností pracuje.

6.1 Syntaktický zápis

Zápis dědičnosti je podle následujícího tvaru

klíč jméno_třídy:seznam_bázových_tříd { složky_třídy }; kde jsou klíč .... class, struct , jméno_třídy je identifikátor odvozené třídy,

seznam_bázových_tříd je výběr tříd, jejichž vlastnosti má odvozená třída dědit a způsob dědění. Položka má tvar [virtual][specifikátor_přístupu]jméno_bázové_třídy , specifikátor_přístupu je jeden z public, protected, private. Složky_třídy jsou definice odvozených tříd.

6.2 Přístupy v dědičnosti

Přístupová práva u děděných vlastností tříd lze řízeně měnit pomocí základních modifikátorů public, protected, private. Podle jednoduché tabulky se mohou skutečné přístupy řídit.

Modifikátor v deklaraci

Modifikátor v bázové třídě

Přístupová práva v odvozené třídě

poznámka

str. 44

Page 45: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

public public public public protected protected public private private protected protected protected protected public protected protected private private private private private private protected private private public private Omezení přístupu způsobené dědičnými právy se mění tak, že zděděnou složku uvedeme bez specifikace typu, ale se specifikací předka. Příklad 25:

class zakl // baze { int i; // private public: int j; // public }; // class odvozena: private zakl // odvozena { int i; // private public: zakl::j; // opet public }; //

Některé překladače mění práva pomocí deklarace using. Příklad 26:

class zakl_x // baze { int e(); // private fc public: int j; // public }; // class odvozena_x: private zakl_x // odvozena { int i; // private public: using zakl_x::fce; // opet public }; //

Dědická práva platí u všech složek i metod třídy. Příklad 27:

str. 45

Page 46: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

class zakl_x // baze { int prom_a, prom_b; // private public: int sou_a(){return prom_a;}; int sou_b(){return prom_b;}; zakl_x: prom_a(10), prom_b(20) {}; }; // class odvozena_x: public zakl_x // odvozena { int ma; // private su public: ozena_x: suma(0){}; // odv int scitej(); { suma+=prom_a+prom_b; return suma; } }; //

V tomto příkladě zřejmě překladač ohlásí chybu, protože je proveden nekorektní zápis odvozené třídy. Složky prom_a, prom_b jsou v odvozené třídě nepřístupné. Jsou dvě možnosti změny. První je, že v základní třídě se změní z private na protected.

class zakl_x // baze { protected: // smi pouzivat potomek int prom_a, prom_b; // private public: int sou_a(){return prom_a;}; int sou_b(){return prom_b;}; zakl_x: prom_a(10), prom_b(20) {}; }; //

Druhá metoda je založena na změně přístupových práv.

class odvozena_x: public zakl_x // odvozena { int suma; // private public: odvozena_x: suma(0){}; // int scitej(); { suma+=sou_a()+sou_b(); return suma; } }; //

str. 46

Page 47: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Konstruktory a destruktory tříd se nedědí, ale při tvorbě případu odvozené třídy jsou zděděné datové složky inicializovány konstruktorem základní třídy. Příklad 28:

class zakl_x // baze { int prom_a; // private public: int sou_a(){return prom_a;}; zakl_x(void): prom_a(10) {}; zakl_x(int prom_b): prom_a(prom_b) {}; }; // class odvozena_x: public zakl_x // odvozena { int ma; // private su public: odvozena_x(void): suma(0){}; // odvozena_x(int prom_b, int prom_c): zakl_x(prom_b),

suma(prom_c){}; // void scitej(zakl_x& b); }; //

V deklaraci konstruktoru odvozena_x(void) nevoláme konstruktor předka. Potom překladač použije konstruktor zakl_x(void) . V konstruktoru odvozena_x(int) se volá konstruktor zakl_x(prom_b) .

6.3 Úkoly

1. Sestavte program pro měřicí ústřednu s okny měřicího zařízení (ručkový měřicí přístroj, osciloskop) tak, aby byly využity vlastnosti dědičnosti měněné podle nastavení uživatele.

7 Polymorfismus

Polymorfismus souvisí s principy dědičnosti. Je tak nazýván jev, kdy jedna metoda (ekv. funkce) je v různých třídách svázaných dědičností, implementována rozdílně.

Vhodné je používat dědění pomocí společné bázové třídy. V odvozených třídách jsou metody předefinovány a tak se pozmění účel metody. Metody, které se mají v odvozených třídách změnit, se deklarují s klíčovým slovem virtual.

Příklad 29:

struct bod_1 {double x,y;}; class kres_obj //

str. 47

Page 48: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

{ protected: bod_1 ref_bod; virtual int kresli(); }; // { //nakresli se bod v danych souradnicich //........ }; // class obdelnik: public kres_obj // { protected: bod_1 rohy[4]; virtual int kresli(); }; // { //nakresli obdelnik o danych rozmerech //........ }; class kruznice: public kres_obj //

//

{ protected: bod_1 stred; float r; virtual int kresli(); }; // { //nakresli kruznici o danych rozmerech //........ }; //

7.1 Úkoly

Sestavte program, který podle příkladu 29 provede v okně vykreslení základních

geometrických obrazců – kružnice, elipsa, čtverec, obdélník, kosočtverec, přímka, trojúhelník,....

8 Přetěžování funkcí

Již jsme o přetěžování kratičce mluvili. Mimo přetěžování funkce z poznámek v předcházejících kapitolách se nyní ještě k tomuto tématu vrátíme v několika odstavcích.

str. 48

Page 49: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

8.1 Přetěžování konstruktorů

Pro snadnější programování a nezatěžování schopností programátora jsou zaváděny všechny systémy přetěžování. Patří mezi ně i přetěžování konstruktorů. Mimo jiné také přetěžování konstruktorů pomáhá k mnohotvárnosti používání polí, tvorbě kopírovacích konstruktorů. Při tvorbě tříd musíme vytvářet konstruktory, pokud nejsou vytvořeny, překladač ohlásí chybu.

Příklad 30: class test { int i;

public: // přetížení konstruktoru dvojí způsobem test(){i=0} //bez inicializátoru test(int n){i=n} //inicializátor

int getx() {return i}; }; int main() { test o1(10); // deklarace s pocatecni hodnotou 2; // deklarace bez inicializatoru test o

cout<<”o1:”<<o1.getx()<< ‘\n ‘; cout<<”o2:”<<o2.getx()<< ‘\n ‘; return 0;

}; V tomto příkladu je dána počáteční hodnota o1, ale není dána o2. Je-li odstraněn

konstruktor, který má prázdný seznam argumentů - test(){i=0}//bez inicializátoru, program nebude úspěšně pracovat. Je-li odstraněn opačně konstruktor s argumenty, výsledek překladu bude stejný test(int n){i=n}//inicializátor. V jiném příkladě se může ukázat výhodnost přetěžování konstruktorů pro to, aby v programu byly jak samostatné objekty, tak pole objektů. Pokud se deklaruje z předchozího příkladu test o1(10); test o1[25]; jsou obě deklarace platné. Pokud se v programu použije parametrizovaných i neparametrizovaných konstruktorů, program umožní vytváření objektů, které mohou nebo nemusí být inicializovány. Příklad 31: class test { int i;

public: // přetížení konstruktoru dvojí způsobem test(){i=0} //bez inicializátoru test(int n){i=n} //inicializátor

str. 49

Page 50: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

int getx() {return i}; }; int main() { test o1[10]; // deklarace pole bez inicializátorů test o2[3]={1,2,3}; // deklarace s inicializatory

.

. return 0;

}; Přetěžováním se dosáhne toho, že programátor si pohodlně může vybrat libovolný typ inicializace objektu. Při přetěžování se může použít prvek – standardní argument. Je to způsob předávání parametrů při volání funkci, které je zkráceným zápisem přetěžování funkce. Zadání standardního argumentu může vypadat například takto: void test_f (int a=0, int b=0); Nyní funkce může být volána třemi způsoby: 1. test_f (); //a,b=0 2. test_f (15); //a=15,b=0 3. test_f (1,56); //a=1, b=56

8.2 Anachronismus přetěžování

V době vzniku C++ bylo pro přetěžování vymezeno klíčové slovo overload. Nyní je zastaralé a není používáno, je možné se s ním setkat ve starších zdrojových textech. Jeho tvar a používání je

overload name_fce; kde name_fce je jméno funkce, která se má přetížit. Příkaz předchází deklaracím přetěžované funkce.

8.3 Přetěžování a nejednoznačnost

Pokud se používá přetěžování funkcí, může se do programu zanést nejednoznačnost. Bývá to převodem typů, pomocí parametrů odkazů, pomocí standardních argumentů. Někdy ale nejednoznačnost je vnesena samotným přetížením funkce. Jednoduchou ukázkou je následující příklad

Příklad 32: float fce_1(float x) { return x/2.0; } double fce_1(double x)

str. 50

Page 51: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

{ return x/3.0; } int main() { float x=1.01; dougle y=1.01, a; a= fce_1(x); // jednoznačné a= fce_1(y); // jednoznačné

a= fce_1(48); // nejednoznačné, převod 48 na double nebo // float???

.

. return 0;

}; Takto by s různými typy šlo pokračovat dále.

8.4 Úkoly

1. Sestavte program, který pomocí zjednodušeného zápisu umožní více typů zobrazení aktuálního data, hodiny.

9 Šablony funkcí a tříd Šablony jsou vzory, podle kterých překladač může sestavit skupiny podobných vlastností.

Tyto skupiny se nazývají případy (instance) šablony. Deklarace šablony má tvar template <seznam_parametru> deklarace; template je klíčové slovo, které uvádí deklaraci šablony, seznam_parametru je seznam formálních parametrů, deklarace je deklarace obyčejné funkce, metody, objektového typu, statické datové složky objektového typu. Šablony nemohou být lokální ve funkcích, šablony funkcí se mohou deklarovat na úrovni souboru, šablony objektových typů můžeme deklarovat na úrovni souboru, jako složky objektových typů nebo šablon objektových typů. Lokální třídy nemohou obsahovat deklarace šablon. Dále existuje ještě několik pravidel nebo zaběhlých použití šablon.

9.1 Parametry šablon

Rozlišují se hodnotové, typové a šablonové parametry. Typový parametr zastupuje

datový typ, hodnotový parametr zastupuje konstantu. Hodnotové parametry se deklarují podobně jako formální parametr funkce. Typový parametr se deklaruje pomocí klíčového slova class. Pokud předepíšeme, že parametr je šablona, získáme poslední typ parametru.

str. 51

Page 52: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Příklad 33: class test // prvni tvar class test =int // druhy tvar typename test // treti tvar typename test=float // ctvrty tvar template< class test, ...>class test_1 // paty tvar template<class test, ... >class test_1=Jmeno_Sablony //sesty tvar První a třetí tvar představuje typový formální parametr bez implicitní hodnoty. Druhá a čtvrtá možnost prezentuje typový formální parametr s implicitní hodnotou. Pátý a šestý tvar zachycují šablonový formální parametr. .

9.2 Šablony funkcí

Zápis šablony funkce je následující template <seznam_parametru> typ jmeno (seznam_parametru_fce ){ telo fce }; Uveďme si na příkladu. Příklad 34: template<class test>test ma(test a, test b) { return a>b?a:b; };

9.3 Šablony objektových typů

Zápis šablony objektového typu je následující template <seznam_parametru> klíč jméno { telo }; Kde klíč je buď class, struct nebo union. Uveďme si na příkladu. Příklad 35: template<typename test, int i=3>class pole{

test x[i]; public:

pole(); };

str. 52

Page 53: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

9.4 Úkoly

Sestavte program, který pomocí šablon zjednoduší výpočet diferencí prvního až n-tého

řádu.

10 Obsluha výjimek

Jazyk C++ má vestavěn mechanismus pro ošetření chyb. Mechanismus je nazýván obsluha výjimek. Toto ošetření se děje pomocí klíčových slov try, catch, throw. Mechanismus pro zpracování výjimek dokáže oddělit běžný zdrojový kód od kódu pro zpracování chyby. Syntaxe je následující try {

pokusny_blok } catch(typ1[identifikator]) { telo_osetreni_vyjimky } catch(typ2[identifikator]) { telo_osetreni_vyjimky } catch(typn[identifikator]) { telo_osetreni_vyjimky };

pokusny_blok je kód, v němž může nastat výjimka, v bloku catch je uveden případ pro zadanou výjimku. Pokud nastane výjimka a není zde uvedeno tělo catch, může dojít k nekorektnímu ukončení programu. Pokud nenastane ani jedna výjimka, všechny bloky catch jsou přeskočeny.

Pokud nechceme přístup k samotné výjimce, v klíčovém slovu catch specifikujeme pouze typ . Pro specifikaci, které výjimky se smějí rozšířit z těla funkce, se používá funkce throw. Pokusme se podívat na nějaký snadný příklad. Příklad 35: void test(int x)throw(int, char, double) { if(x==0) throw x; //odmitne int if(x==1) throw ’abcd’; //odmitne char if(x==2) throw 122.333; //odmitne double if(x==0) throw x; // } int main()

str. 53

Page 54: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

{ int err=0;

try{ test (0)} catch(int i) { err=1; } catch(char c) { err=2; } catch(double d) { err=3; }

return err; } V příkladu je definovaná funkce test, která zachycuje výjimky s omezené množiny (celé číslo, znak, reálné s dvounásobnou přesností). V hlavní funkci se deklaruje proměnná err a volá se blok try s funkcí test. Níže jsou zachyceny výjimky a podle jejich pořadí je do proměnné err zapsána hodnota. Ta se na konci hlavní funkce předá. Jako doplnění pro ošetření výjimek slouží funkce unexpected(), terminate(), set_unexpected(), set_terminate(). Funkce unexpected(), terminate() volá systém v případě, že se má ukončit program. Funkce set_unexpected(), set_terminate() mohou změnit nastavení funkcí unexpected(), terminate().

10.1 Úkoly

1. Pro váš sestavený program nastavte kontrolu neočekávaných výjimek tak, abyste ošetřili program proti nestandardnímu ukončení.

11 Závěr

Společně jsme prošli základy programování v jazyce C++ a velmi bodově jsme se dotkli některých témat jazyka. Měli bychom získat základní návyky programátora, naučit se používat různé druhy vysvětlujících textů. Největší škola programování je vlastní práce s jasně definovaným cílem. K tomuto kurzu se nabízelo použití vývojového prostředí Borland C++ Builder pro platformu MS Windows. Kurz se zaměřil z 90-ti procent na programy klasického typu (na událostmi řízené programování se orientoval kurz Počítače a programování II). Tím jsme učinili první krok k tomu, abychom byli schopni vyvíjet praktické aplikace pro řešení problémů z oblasti elektrotechniky, informatiky a komunikačních technologií.

str. 54

Page 55: Seminar Cpp S

Seminář C++ VUT FEKT v Brně

Pevně věřím, že nabyté znalosti využijete i ve svém další studiu při práci na ročníko-vých projektech, na bakalářských a diplomových pracích.

Musíme si však uvědomit, že náš základní kurs pokryl základy programování C++. Tyto základy budete muset již sami ve své další práci rozvíjet, budete se muset sami seznamovat s dalšími možnostmi, které Borland C++ Builder a další nadplatformní programy nabízí, a sami budete muset bedlivě sledovat vývoj, jímž programovací nástroje procházejí. Určitě není třeba upozorňovat na skutečnost, že informační technologie se vyvíjejí velmi bouřlivě a že programátoři musejí studovat nové technologie celý život.

Při tomto neustálém studiu vám přeji mnoho úspěchů.

11.1 Literatura

[1] ECKEL, B. Myslíme v jazyku C++. Praha: Grada Publishing, 2002. ISBN 8-0247-9009-2

[2] VIRIUS, M. Programovací jazyky C/C++. Praha: Gcomp, 1992. ISBN 8-0901-0735-4.

[3] PRATA, S. Mistrovství v C++. Praha: Computer Press, 2001. ISBN 8-0722-6339-0

[4] KADLEC, V. Učíme se programovat v Borland C++ Builder a jazyce C++. Praha: Computer Press, 2001. ISBN 8-0722-6550-4

[5] HOLAN, T., NERUDA, R. C++ Builder v příkladech. Praha: BEN, 2002. ISBN 8-0730-0042-3

[6] HEROUT, P. Učebnice jazyka C. České Budějovice: Kopp, 1992. ISBN 8-0858-2821-9

[7] HEROUT, P. Učebnice jazyka C, 2.díl. Č. Budějovice: Kopp, 1992. ISBN 80-85828-50-2

[8] Virius,M.a kol. Jazyky C a C++ podle normy ANSI/ISO. GRADA, 1999. ISBN 80-7169-631-5

[9] Schildt,H. Nauč se sám C++. Softpress, 2001. ISBN 80-86497-13-5

str. 55


Recommended